From: liulongfang <liulongfang@huawei.com>
To: Matt Evans <matt@ozlabs.org>
Cc: "Alex Williamson" <alex@shazbot.org>,
"Leon Romanovsky" <leon@kernel.org>,
"Jason Gunthorpe" <jgg@nvidia.com>,
"Alex Mastro" <amastro@fb.com>,
"Christian König" <christian.koenig@amd.com>,
"Bjorn Helgaas" <bhelgaas@google.com>,
"Logan Gunthorpe" <logang@deltatee.com>,
"Kevin Tian" <kevin.tian@intel.com>,
"Pranjal Shrivastava" <praan@google.com>,
"Mahmoud Adam" <mngyadam@amazon.de>,
"David Matlack" <dmatlack@google.com>,
"Björn Töpel" <bjorn@kernel.org>,
"Sumit Semwal" <sumit.semwal@linaro.org>,
"Ankit Agrawal" <ankita@nvidia.com>,
"Alistair Popple" <apopple@nvidia.com>,
"Vivek Kasireddy" <vivek.kasireddy@intel.com>,
linux-kernel@vger.kernel.org, linux-media@vger.kernel.org,
dri-devel@lists.freedesktop.org, linaro-mm-sig@lists.linaro.org,
kvm@vger.kernel.org, linux-pci@vger.kernel.org
Subject: Re: [PATCH v6 5/9] vfio/pci: Add a helper to create a DMABUF for a BAR-map VMA
Date: Tue, 22 Sep 2026 17:16:56 +0800 [thread overview]
Message-ID: <f8eb95a8-875e-fb31-a2a2-ffa1c531dedb@huawei.com> (raw)
In-Reply-To: <4f26dd49-0985-4049-a1fe-6a0a493c7a51@ozlabs.org>
On 2026/9/21 21:24, Matt Evans wrote:
> Hi Longfang,
>
> On 15/09/2026 13:16, liulongfang wrote:
>> On 2026/9/12 5:41, Matt Evans wrote:
>>> This helper, vfio_pci_core_mmap_prep_dmabuf(), creates a single-range
>>> DMABUF for the purpose of mapping a PCI BAR. This is used in a future
>>> commit by VFIO's ordinary mmap() path.
>>>
>>> This function transfers ownership of the VFIO device fd to the
>>> DMABUF, which fput()s when it's released.
>>>
>>> Refactor the existing vfio_pci_core_feature_dma_buf() to split out
>>> export code common to the two paths, VFIO_DEVICE_FEATURE_DMA_BUF and
>>> this new VFIO_BAR mmap().
>>>
>>> By exchanging the VMA file, we lose the original device path in
>>> /proc/<pid>/maps, lsof, etc. Generate a debug-oriented synthetic
>>> 'filename' for BAR mappings based on the cdev, plus BDF, plus resource
>>> index. (This does not apply to explicitly-exported DMABUFs which are
>>> named by DMA_BUF_SET_NAME.)
>>>
>>> Signed-off-by: Matt Evans <matt@ozlabs.org>
>>> ---
>>> drivers/vfio/pci/vfio_pci_dmabuf.c | 211 +++++++++++++++++++++++------
>>> drivers/vfio/pci/vfio_pci_priv.h | 5 +
>>> 2 files changed, 171 insertions(+), 45 deletions(-)
>>>
>>> diff --git a/drivers/vfio/pci/vfio_pci_dmabuf.c b/drivers/vfio/pci/vfio_pci_dmabuf.c
>>> index 9f10b10fc436..faa9239e66f8 100644
>>> --- a/drivers/vfio/pci/vfio_pci_dmabuf.c
>>> +++ b/drivers/vfio/pci/vfio_pci_dmabuf.c
>>> @@ -3,6 +3,7 @@
>>> */
>>> #include <linux/dma-buf-mapping.h>
>>> #include <linux/pci-p2pdma.h>
>>> +#include <linux/dma-buf.h>
>>> #include <linux/dma-resv.h>
>>>
>>> #include "vfio_pci_priv.h"
>>> @@ -82,6 +83,8 @@ static void vfio_pci_dma_buf_release(struct dma_buf *dmabuf)
>>> up_write(&priv->vdev->dmabuf_lock);
>>> vfio_device_put_registration(&priv->vdev->vdev);
>>> }
>>> + if (priv->vfile)
>>> + fput(priv->vfile);
>>> kfree(priv->phys_vec);
>>> kfree(priv);
>>> }
>>> @@ -246,6 +249,167 @@ int vfio_pci_dma_buf_find_pfn(struct vfio_pci_core_device *vdev,
>>> return ret;
>>> }
>>>
>>> +/*
>>> + * Create a DMABUF corresponding to priv, add it to vdev->dmabufs list
>>> + * for tracking (meaning cleanup or revocation will zap it), and take
>>> + * a vfio_device registration.
>>> + */
>>> +static int vfio_pci_dmabuf_export(struct vfio_pci_core_device *vdev,
>>> + struct vfio_pci_dma_buf *priv, u32 flags)
>>> +{
>>> + DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
>>> +
>>> + if (!vfio_device_try_get_registration(&vdev->vdev))
>>> + return -ENODEV;
>>> +
>>> + exp_info.ops = &vfio_pci_dmabuf_ops;
>>> + exp_info.size = priv->size;
>>> + exp_info.flags = flags;
>>> + exp_info.priv = priv;
>>> +
>>> + priv->dmabuf = dma_buf_export(&exp_info);
>>> + if (IS_ERR(priv->dmabuf)) {
>>> + vfio_device_put_registration(&vdev->vdev);
>>> + return PTR_ERR(priv->dmabuf);
>>> + }
>>> +
>>> + kref_init(&priv->kref);
>>> + init_completion(&priv->comp);
>>> +
>>> + /* dma_buf_put() now frees priv */
>>> + INIT_LIST_HEAD(&priv->dmabufs_elm);
>>> +
>>> + /*
>>> + * dmabuf_lock synchronises access (R) or updates (W) to the
>>> + * vdev->dmabufs list and to bars_revoked (see below). The
>>> + * revocation state of DMABUF elements in the list is written
>>> + * holding both dmabuf_lock(W) and resv, and tested with
>>> + * either.
>>> + *
>>> + * (memory_lock, if held ->) dmabuf_lock -> resv
>>> + *
>>> + * NOTE: memory_lock is strictly avoided here, to avoid a
>>> + * dependency on memory_lock when mmap_lock is held, when
>>> + * mmap() leads to export. vfio-pci variant drivers are
>>> + * permitted to hold memory_lock across actions that might
>>> + * fault (such as user access); a deadlock could result when
>>> + * that fault path attempts to take mmap_lock (if held by an
>>> + * export waiting for memory_lock).
>>> + *
>>> + * vdev->bars_revoked tracks the BAR revocation status updated
>>> + * via vfio_pci_dma_buf_move(), so the initial DMABUF state
>>> + * follows the same criteria that later update the DMABUF
>>> + * state (BAR zap, etc.).
>>> + */
>>> + lockdep_assert_not_held(&vdev->memory_lock);
>>> +
>>> + down_write(&vdev->dmabuf_lock);
>>> + dma_resv_lock(priv->dmabuf->resv, NULL);
>>> + priv->revoked = vdev->bars_revoked;
>>> + list_add_tail(&priv->dmabufs_elm, &vdev->dmabufs);
>>> + dma_resv_unlock(priv->dmabuf->resv);
>>> + up_write(&vdev->dmabuf_lock);
>>> +
>>> + return 0;
>>> +}
>>> +
>>> +int vfio_pci_core_mmap_prep_dmabuf(struct vfio_pci_core_device *vdev,
>>> + struct vm_area_struct *vma,
>>> + u64 phys_start, u64 req_len,
>>> + unsigned int res_index)
>>> +{
>>> + struct vfio_pci_dma_buf *priv;
>>> + unsigned long vma_pgoff = vma->vm_pgoff & (VFIO_PCI_OFFSET_MASK >> PAGE_SHIFT);
>>> + char *bufname;
>>> + int ret;
>>> +
>>> + priv = kzalloc_obj(*priv);
>>> + if (!priv)
>>> + return -ENOMEM;
>>> +
>>> + priv->phys_vec = kzalloc_obj(*priv->phys_vec);
>>> + if (!priv->phys_vec) {
>>> + ret = -ENOMEM;
>>> + goto err_free_priv;
>>> + }
>>> +
>>> + /*
>>> + * Maximum size of the friendly debug name is
>>> + * vfio1048575:ffff:ff:1f.7/5 = 26. This fits within
>>> + * DMA_BUF_NAME_LEN, so dma_buf_set_name() below won't fail.
>>> + */
>>> + bufname = kasprintf(GFP_KERNEL, "%s:%s/%x",
>>> + dev_name(&vdev->vdev.device), pci_name(vdev->pdev),
>>> + res_index);
>>> +
>>> + if (!bufname) {
>>> + ret = -ENOMEM;
>>> + goto err_free_phys;
>>> + }
>>> +
>>> + /*
>>> + * The DMABUF begins from the mmap()'s BAR offset, i.e. the
>>> + * start of the VMA corresponds to byte 0 of the DMABUF and
>>> + * byte (vma_pgoff << PAGE_SHIFT) of the BAR.
>>> + *
>>> + * vfio_pci_dma_buf_find_pfn() reverses this offset using
>>> + * vma_pgoff_adjust, so that ultimately a fault's offset from
>>> + * the start of the _VMA_ has a consistent usage whether the
>>> + * VMA originates from an mmap() of the VFIO device here or a
>>> + * direct DMABUF mmap(). Note vma_pgoff_adjust also includes
>>> + * the encoded VFIO region index, which cancels out the index
>>> + * encoded in vm_pgoff.
>>> + */
>>> + priv->vdev = vdev;
>>> + priv->size = req_len;
>>> + priv->nr_ranges = 1;
>>> + priv->vma_pgoff_adjust = vma->vm_pgoff;
>>> +
>>> + priv->provider = pcim_p2pdma_provider(vdev->pdev, res_index);
>>> + if (!priv->provider) {
>>> + ret = -EINVAL;
>>> + goto err_free_name;
>>> + }
>>> +
>>> + priv->phys_vec[0].paddr = phys_start + ((u64)vma_pgoff << PAGE_SHIFT);
>>> + priv->phys_vec[0].len = priv->size;
>>> +
>>> + ret = vfio_pci_dmabuf_export(vdev, priv, O_RDWR);
>>> + if (ret)
>>> + goto err_free_name;
>>> +
>>
>> In the current patch, the PCIe device's BAR2 configuration space can be mapped as a DMABUF.
>> However, on an OS with a 64K page size, if a VF device's BAR2 is smaller than 64K,
>> a problem arises where the space is forced to page-align to 64K, it will causing the VM to
>> access memory beyond the actual size of the VF device's BAR2 space.
>>
>> How does your solution handle these cases where the BAR2 space is smaller than the Host OS's page size?
>
> Even on a 4K host, there can be BARs < PAGE_SIZE so 64K (or 16K) hosts
> aren't a new case. These small BARs cannot be mmap()ed and DMABUFs
> cannot be exported from them. (vfio_pci_core_mmap() errors out when
> !bar_mmap_supported[index]. And, a DMABUF needs to be an aligned
> multiple of PAGE_SIZE, plus vfio_pci_core_fill_phys_vec() won't allow a
> DMABUF to be created off the end of a BAR.)
>
> So, although this series allows a DMABUF to be mmap()ed, the preexisting
> checks prevent a sub-page DMABUF from existing and so there is no new
> route to mapping a sub-page BAR.
>
> What's the concern on BAR2 specifically, out of interest? This logic is
> applied to all resources equally, and tests pci_resource_len(...) so
> there shouldn't be a PF/VF distinction either.
>
However, the typical boundary check found in VFIO, such as:
if (req_start + req_len > phys_len)
return -EINVAL;
seems to be missing here.
Thanks.
Longfang.
>
> Matt
>
>>
>> Thanks.
>> Longfang.
>>
>>> + if (dma_buf_set_name(priv->dmabuf, bufname)) {
>>> + /* Shouldn't happen, but don't leak if it does: */
>>> + dev_dbg_ratelimited(&vdev->pdev->dev,
>>> + "Failed to set map name '%s'\n",
>>> + bufname);
>>> + kfree(bufname);
>>> + }
>>> +
>>> + /*
>>> + * Ownership of the DMABUF file transfers to the VMA so that
>>> + * other users can locate the DMABUF via a VA. Ownership of
>>> + * the original VFIO device file being mmap()ed transfers to
>>> + * priv, and is put when the DMABUF is released. This
>>> + * intentionally does not use get_file()/vma_set_file()
>>> + * because the references are already held, and ownership
>>> + * moves.
>>> + */
>>> + priv->vfile = vma->vm_file;
>>> + vma->vm_file = priv->dmabuf->file;
>>> + vma->vm_private_data = priv;
>>> +
>>> + return 0;
>>> +
>>> +err_free_name:
>>> + kfree(bufname);
>>> +err_free_phys:
>>> + kfree(priv->phys_vec);
>>> +err_free_priv:
>>> + kfree(priv);
>>> + return ret;
>>> +}
>>> +
>>> /*
>>> * This is a temporary "private interconnect" between VFIO DMABUF and iommufd.
>>> * It allows the two co-operating drivers to exchange the physical address of
>>> @@ -364,7 +528,6 @@ int vfio_pci_core_feature_dma_buf(struct vfio_pci_core_device *vdev, u32 flags,
>>> {
>>> struct vfio_device_feature_dma_buf get_dma_buf = {};
>>> struct vfio_region_dma_range *dma_ranges;
>>> - DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
>>> struct vfio_pci_dma_buf *priv;
>>> size_t length;
>>> int ret;
>>> @@ -424,49 +587,9 @@ int vfio_pci_core_feature_dma_buf(struct vfio_pci_core_device *vdev, u32 flags,
>>> kfree(dma_ranges);
>>> dma_ranges = NULL;
>>>
>>> - if (!vfio_device_try_get_registration(&vdev->vdev)) {
>>> - ret = -ENODEV;
>>> + ret = vfio_pci_dmabuf_export(vdev, priv, get_dma_buf.open_flags);
>>> + if (ret)
>>> goto err_free_phys;
>>> - }
>>> -
>>> - exp_info.ops = &vfio_pci_dmabuf_ops;
>>> - exp_info.size = priv->size;
>>> - exp_info.flags = get_dma_buf.open_flags;
>>> - exp_info.priv = priv;
>>> -
>>> - priv->dmabuf = dma_buf_export(&exp_info);
>>> - if (IS_ERR(priv->dmabuf)) {
>>> - ret = PTR_ERR(priv->dmabuf);
>>> - goto err_dev_put;
>>> - }
>>> -
>>> - kref_init(&priv->kref);
>>> - init_completion(&priv->comp);
>>> -
>>> - /* dma_buf_put() now frees priv */
>>> - INIT_LIST_HEAD(&priv->dmabufs_elm);
>>> -
>>> - /*
>>> - * dmabuf_lock synchronises access (R) or updates (W) to the
>>> - * vdev->dmabufs list and to bars_revoked (see below). The
>>> - * revocation state of DMABUF elements in the list is written
>>> - * holding both dmabuf_lock(W) and resv, and tested with
>>> - * either.
>>> - *
>>> - * dmabuf_lock -> resv
>>> - *
>>> - * vdev->bars_revoked tracks the BAR revocation status updated
>>> - * via vfio_pci_dma_buf_move(), so the initial DMABUF state
>>> - * follows the same criteria that later update the DMABUF
>>> - * state (BAR zap, etc.).
>>> - */
>>> - down_write(&vdev->dmabuf_lock);
>>> - dma_resv_lock(priv->dmabuf->resv, NULL);
>>> - priv->revoked = vdev->bars_revoked;
>>> - list_add_tail(&priv->dmabufs_elm, &vdev->dmabufs);
>>> - dma_resv_unlock(priv->dmabuf->resv);
>>> - up_write(&vdev->dmabuf_lock);
>>> -
>>> /*
>>> * dma_buf_fd() consumes the reference, when the file closes the dmabuf
>>> * will be released.
>>> @@ -477,8 +600,6 @@ int vfio_pci_core_feature_dma_buf(struct vfio_pci_core_device *vdev, u32 flags,
>>>
>>> return ret;
>>>
>>> -err_dev_put:
>>> - vfio_device_put_registration(&vdev->vdev);
>>> err_free_phys:
>>> kfree(priv->phys_vec);
>>> err_free_priv:
>>> diff --git a/drivers/vfio/pci/vfio_pci_priv.h b/drivers/vfio/pci/vfio_pci_priv.h
>>> index 48d9f574a3df..3ec676e12e21 100644
>>> --- a/drivers/vfio/pci/vfio_pci_priv.h
>>> +++ b/drivers/vfio/pci/vfio_pci_priv.h
>>> @@ -30,6 +30,7 @@ struct vfio_pci_dma_buf {
>>> size_t size;
>>> struct phys_vec *phys_vec;
>>> struct p2pdma_provider *provider;
>>> + struct file *vfile;
>>> u32 nr_ranges;
>>> struct kref kref;
>>> struct completion comp;
>>> @@ -134,6 +135,10 @@ int vfio_pci_dma_buf_find_pfn(struct vfio_pci_core_device *vdev,
>>> unsigned long address,
>>> unsigned int order,
>>> unsigned long *out_pfn);
>>> +int vfio_pci_core_mmap_prep_dmabuf(struct vfio_pci_core_device *vdev,
>>> + struct vm_area_struct *vma,
>>> + u64 phys_start, u64 req_len,
>>> + unsigned int res_index);
>>>
>>> #ifdef CONFIG_VFIO_PCI_DMABUF
>>> int vfio_pci_core_feature_dma_buf(struct vfio_pci_core_device *vdev, u32 flags,
>>>
>
> .
>
next prev parent reply other threads:[~2026-09-22 9:17 UTC|newest]
Thread overview: 37+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-11 21:41 [PATCH v6 0/9] vfio/pci: Add mmap() for DMABUFs Matt Evans
2026-09-11 21:41 ` [PATCH v6 1/9] vfio/pci: Remove DMABUF export dependency on vdev->memory_lock Matt Evans
2026-09-11 21:41 ` [PATCH v6 2/9] vfio/pci: Un-revoke DMABUFs in LOW_POWER_ENTRY_WITH_WAKEUP resume Matt Evans
2026-09-11 21:41 ` [PATCH v6 3/9] dma-buf: Export dma_buf_set_name() Matt Evans
2026-09-14 11:06 ` Christian König
2026-09-15 13:35 ` Matt Evans
2026-09-11 21:41 ` [PATCH v6 4/9] vfio/pci: Add a helper to look up PFNs for DMABUFs Matt Evans
2026-09-11 21:41 ` [PATCH v6 5/9] vfio/pci: Add a helper to create a DMABUF for a BAR-map VMA Matt Evans
2026-09-15 12:16 ` liulongfang
2026-09-21 13:24 ` Matt Evans
2026-09-22 9:16 ` liulongfang [this message]
2026-09-11 21:41 ` [PATCH v6 6/9] vfio/pci: Convert BAR mmap() to use a DMABUF Matt Evans
2026-09-11 21:41 ` [PATCH v6 7/9] vfio/pci: Clean up BAR zap and revocation Matt Evans
2026-09-11 21:41 ` [PATCH v6 8/9] vfio/pci: Support mmap() of a VFIO DMABUF Matt Evans
2026-09-11 21:41 ` [PATCH v6 9/9] vfio/pci: Permanently revoke a DMABUF on request Matt Evans
2026-09-13 16:52 ` Leon Romanovsky
2026-09-14 11:36 ` Jason Gunthorpe
2026-09-14 11:54 ` Leon Romanovsky
2026-09-14 11:58 ` Jason Gunthorpe
2026-09-14 12:06 ` Leon Romanovsky
2026-09-14 12:08 ` Jason Gunthorpe
2026-09-14 12:13 ` Matt Evans
2026-09-15 7:20 ` Leon Romanovsky
2026-09-15 11:13 ` Christian König
2026-09-15 14:22 ` Matt Evans
2026-09-16 14:19 ` Christian König
2026-09-21 13:08 ` Matt Evans
2026-09-21 13:22 ` Jason Gunthorpe
2026-09-21 13:45 ` Christian König
2026-09-21 13:49 ` Jason Gunthorpe
2026-09-21 14:09 ` Christian König
2026-09-22 12:41 ` Jason Gunthorpe
2026-09-22 12:46 ` Leon Romanovsky
2026-09-22 12:54 ` Jason Gunthorpe
2026-09-22 11:40 ` Leon Romanovsky
2026-09-15 12:35 ` Jason Gunthorpe
2026-09-15 14:30 ` Matt Evans
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=f8eb95a8-875e-fb31-a2a2-ffa1c531dedb@huawei.com \
--to=liulongfang@huawei.com \
--cc=alex@shazbot.org \
--cc=amastro@fb.com \
--cc=ankita@nvidia.com \
--cc=apopple@nvidia.com \
--cc=bhelgaas@google.com \
--cc=bjorn@kernel.org \
--cc=christian.koenig@amd.com \
--cc=dmatlack@google.com \
--cc=dri-devel@lists.freedesktop.org \
--cc=jgg@nvidia.com \
--cc=kevin.tian@intel.com \
--cc=kvm@vger.kernel.org \
--cc=leon@kernel.org \
--cc=linaro-mm-sig@lists.linaro.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-media@vger.kernel.org \
--cc=linux-pci@vger.kernel.org \
--cc=logang@deltatee.com \
--cc=matt@ozlabs.org \
--cc=mngyadam@amazon.de \
--cc=praan@google.com \
--cc=sumit.semwal@linaro.org \
--cc=vivek.kasireddy@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®