On Mon, Oct 19, 2026 at 09:14:07AM +0200, Karl Mehltretter wrote:
> UVC and vivid access imported DMA-BUFs with the CPU without cache
> synchronization. On a Pi 400, captured data remained in the CPU cache
> while physical RAM was stale.
>
> Add an opt-in queue flag to bracket CPU access from buf_prepare() through
> buf_finish(). The allocator cannot imply CPU use because some vb2-vmalloc
> drivers pass buffers to hardware. Patch 1 balances finish operations in
> VIDIOC_REMOVE_BUFS so removing prepared buffers closes this interval.
This seems completely wrong.
> This follows the per-queue flag proposed here:
> https://lists.openwall.net/linux-kernel/2024/06/20/236
>
> Based on Linux 7.3. Tests cover the same code on these earlier bases:
>
> - Pi 400, 7.3-rc4, all four patches: eight 640x480 YUYV frames per run,
> imported CMA DMA-BUFs with a DRM device mapping:
>
> Path Runs Stale frames
> UVC, vb2-vmalloc 12 0/96
> vivid, vb2-vmalloc 12 0/96
> vivid, vb2-dma-contig 12 0/96
>
> All six lifecycle cases passed with both vivid allocators. Read-only
> output USERPTR passed. The test added no warnings or failed CPU-access
> callbacks. A control without the DRM mapping found 4/16 stale frames.
>
> - SAM9X75 (ARMv5), 6.18 backport of all four patches: the baseline
> PREPARE_BUF/REMOVE_BUFS imbalance was fixed. USERPTR and six lifecycle
> cases passed. All 128 vivid and 96 UVC frames matched RAM, with 100/100
> begin/end calls. The baseline was already coherent.
>
> - BeagleV Ahead (RISC-V), 7.3-rc7, patches 1, 2 and 4: read-only USERPTR,
> six traced lifecycle cases and 60 repeats passed with balanced callbacks
> and no kernel diagnostics. A vendor 5.10 backport of patches 2 and 3
> captured 96 UVC frames without stale data, with 100/100 begin/end calls.
> Its baseline was already coherent.
>
> Karl Mehltretter (4):
> media: videobuf2: finish prepared buffers in VIDIOC_REMOVE_BUFS
> media: videobuf2: add opt-in DMA-BUF CPU access
> media: uvcvideo: synchronize imported DMA-BUFs for CPU access
> media: vivid: synchronize imported DMA-BUFs for CPU access
>
> .../media/common/videobuf2/videobuf2-core.c | 96 ++++++++++++++++++-
> .../common/videobuf2/videobuf2-dma-contig.c | 5 +-
> .../media/common/videobuf2/videobuf2-dma-sg.c | 5 +-
> .../common/videobuf2/videobuf2-vmalloc.c | 5 +-
> drivers/media/test-drivers/vivid/vivid-core.c | 1 +
> drivers/media/usb/uvc/uvc_queue.c | 1 +
> include/media/videobuf2-core.h | 12 ++-
> 7 files changed, 116 insertions(+), 9 deletions(-)
>
>
> base-commit: c03c1a14507dfaf8b856c2608f9ac216021fc222
--
Regards,
Laurent Pinchart
On Thu, 1 Oct 2026 16:56:46 +0200
Olivier Moysan <olivier.moysan(a)foss.st.com> wrote:
> Add the STM32 Multi-function Digital Filter (MDF) core, serial interface
> and digital filter drivers. The MDF converts bitstreams from sigma-delta
> modulators or digital microphones into samples exposed through IIO.
>
> Audio: capture PDM microphones via cyclic DMA for an ASoC consumer.
> Support CIC scaling and filtering, synchronized and interleaving modes.
> Audio use case requires a DMIC filter, and a separate ASoC DAI.
>
> Analog: expose sigma-delta modulators as IIO voltage channels with
> direct reads or DMA buffering mode. STM32 timer triggers can be used as
> clock source.
> Analog use case requires an IIO backend for the SD modulator.
>
> Signed-off-by: Olivier Moysan <olivier.moysan(a)foss.st.com>
I'm not going to spend long on this today, but a few trivial things noted
from a quick glance.
> diff --git a/drivers/iio/adc/stm32-mdf-serial.c b/drivers/iio/adc/stm32-mdf-serial.c
> new file mode 100644
> index 000000000000..15a58cf833be
> --- /dev/null
> +++ b/drivers/iio/adc/stm32-mdf-serial.c
...
> +
> +int stm32_mdf_sitf_stop(struct stm32_mdf_sitf *sitf)
> +{
> + int ret = 0;
> +
> + spin_lock(&sitf->lock);
Use guard() for cases like this. Simplifies the flow and helps
readabilty as a result. Everyone loves an early return.
> +
> + if (!sitf->refcnt) {
> + dev_err(sitf->dev, "Unbalanced serial interface stop ?\n");
> + ret = -EPERM;
> + goto out;
> + } else {
> + sitf->refcnt--;
> + }
> +
> + if (!sitf->refcnt)
> + ret = regmap_clear_bits(sitf->regmap, MDF_SITFCR_REG, MDF_SITFCR_SITFEN);
> +
> +out:
> + spin_unlock(&sitf->lock);
> +
> + return ret;
> +}
> +EXPORT_SYMBOL_GPL(stm32_mdf_sitf_stop);
>
> +static int stm32_mdf_sitf_runtime_suspend(struct device *dev)
> +{
Add a comment on why you need these.
> + return 0;
> +}
> +
> +static int stm32_mdf_sitf_runtime_resume(struct device *dev)
> +{
> + return 0;
> +}
> diff --git a/drivers/iio/adc/stm32-mdf.h b/drivers/iio/adc/stm32-mdf.h
> new file mode 100644
> index 000000000000..7e403c26d4dc
> --- /dev/null
> +++ b/drivers/iio/adc/stm32-mdf.h
> @@ -0,0 +1,312 @@
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +/*
> + * This file is part of STM32 MDF driver
> + *
> + * Copyright (C) 2023, STMicroelectronics - All Rights Reserved
I'd guess you'll modify it enough that this might need
an update!
> +/* MDF_SIDR: Size Identification Register */
> +#define MDF_SIDR_SID_MASK GENMASK(31, 0)
> +#define MDF_SIDR_SID(v) FIELD_PREP(MDF_SIDR_SID_MASK, v)
I'd not bother with the second macro. It is only a little
shorter than FIELD_PREP() in most case.
>
On Thu, 15 Oct 2026 08:36:35 +0000, Deep Shah wrote:
> Fix two lifetime bugs in the uverbs DMABUF export path. Patch 1 fixes
> leaked uobject and ufile references when the uverbs FD is closed first.
> Patch 2 fixes a use-after-free when dma-buf release races with ufile
> cleanup.
>
> Tested on mainline 4056b3c9d3c9 in x86_64 QEMU with KASAN and lockdep,
> using test-only siw export hooks. The unpatched kernel reproduces both
> bugs. Patch 1 fixes the leak, confirmed by tracing ufile release. With
> both patches, the same tests complete without KASAN or lockdep reports.
>
> [...]
Applied, thanks!
[1/2] RDMA/uverbs: Fix uobject leak in DMABUF release
https://git.kernel.org/rdma/rdma/c/4a953ee228f554
[2/2] RDMA/uverbs: Fix DMABUF use-after-free during ufile cleanup
https://git.kernel.org/rdma/rdma/c/2854f9025d4ef6
Best regards,
--
Leon Romanovsky <leon(a)kernel.org>
Hi Karl,
> Subject: Re: [PATCH v2] udmabuf: respect the device's maximum
> segment size
>
> On Tue, Sep 29, 2026 at 07:48:35AM +0100, Karl Mehltretter wrote:
> > get_sg_table() merges physically contiguous pages without accounting
> > for the mapping device's maximum segment size. This affects both
> > importer mappings and the udmabuf misc device mapping used for
> CPU
> > access.
> >
> > With DMA_API_DEBUG enabled, DMA_BUF_IOCTL_SYNC on a 64 MiB
> udmabuf
> > reports:
> >
> > DMA-API: misc udmabuf: mapping sg segment longer than device
> claims to
> > support [len=65884160] [max=65536]
> >
> > Use sg_alloc_table_from_pages_segment() with the mapping device's
> > maximum segment size. Return -EINVAL if the limit is smaller than
> > PAGE_SIZE because the page-based allocator cannot honor it.
> >
> > Before commit 5bf888673e0d ("udmabuf: Do not create malformed
> > scatterlists"), each entry covered one page.
> >
> > Fixes: 5bf888673e0d ("udmabuf: Do not create malformed
> scatterlists")
> > Reviewed-by: Jason Gunthorpe <jgg(a)nvidia.com>
> > Assisted-by: LLM
> > Signed-off-by: Karl Mehltretter <kmehltretter(a)gmail.com>
>
> Friendly ping on v2. It has Reviewed-by tags from Jason and Christian.
Will push this patch to drm-misc-next soon (in a day or two).
Thanks,
Vivek
>
> Thanks,
> Karl
On Thu, Oct 15, 2026 at 01:08:33PM +0530, Jayant Shekhar wrote:
> diff --git a/arch/arm64/boot/dts/qcom/hawi.dtsi b/arch/arm64/boot/dts/qcom/hawi.dtsi
> index 0926d880cb0c..58fcf42cbaba 100644
> --- a/arch/arm64/boot/dts/qcom/hawi.dtsi
> +++ b/arch/arm64/boot/dts/qcom/hawi.dtsi
> @@ -8235,4 +8235,63 @@ timer {
> <GIC_PPI 11 IRQ_TYPE_LEVEL_LOW>,
> <GIC_PPI 10 IRQ_TYPE_LEVEL_LOW>;
> };
> +
> + dcp: virtio@9be8000 {
> + compatible = "qcom,dcp-virtio", "virtio,mmio";
More slop.
At least you could ask your agent to TEST it. See internal guidelines
how to do it.
Best regards,
Krzysztof
On Thu, Oct 15, 2026 at 01:08:21PM +0530, Jayant Shekhar wrote:
> DCP platforms place the display pipeline under firmware control, so Linux
> cannot discover display resources through direct register access. The DRM
> driver therefore needs device-tree descriptions of the firmware transport,
> display topology, IOMMU contexts, and panel connections.
Due to dependencies this cannot be tested, so limited review.
A nit, subject: drop second/last, redundant "bindings". The
"dt-bindings" prefix is already stating that these are bindings.
See also:
https://elixir.bootlin.com/linux/v7.1-rc7/source/Documentation/devicetree/b…
>
> Add bindings for the Qualcomm DCP VirtIO display function, including the
> INTF graph and DSI host outputs. Document the framebuffer IOMMU context,
> IPCC power-notify mailbox and interrupts, firmware display topology, and
> firmware-visible IOVA window supplied by the parent VirtIO-MMIO transport.
>
> Signed-off-by: Jayant Shekhar <jayant.shekhar(a)oss.qualcomm.com>
> Assisted-by: LLM
> ---
> .../bindings/display/msm/qcom,dcp-dsi.yaml | 75 +++++++++++++
> .../bindings/display/msm/qcom,dcp-virtio.yaml | 113 +++++++++++++++++++
> .../devicetree/bindings/display/msm/qcom,dcp.yaml | 119 +++++++++++++++++++++
> 3 files changed, 307 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/display/msm/qcom,dcp-dsi.yaml b/Documentation/devicetree/bindings/display/msm/qcom,dcp-dsi.yaml
> new file mode 100644
> index 000000000000..f7178c66c09e
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/display/msm/qcom,dcp-dsi.yaml
> @@ -0,0 +1,75 @@
> +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/display/msm/qcom,dcp-dsi.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Qualcomm DCP DSI host
> +
> +maintainers:
> + - Jayant Shekhar <jayant.shekhar(a)oss.qualcomm.com>
> +
> +description: |
> + A MIPI DSI host exposed by the Qualcomm DCP VirtIO device (see
> + qcom,dcp.yaml). DCP is a firmware protocol shared across multiple
> + Qualcomm SoCs, not specific to any one of them; Hawi is its first
> + platform. The DSI host and its connection to a panel are described
> + using the standard DSI controller and OF graph properties.
> +
> +allOf:
> + - $ref: /schemas/display/dsi-controller.yaml#
> +
> +properties:
> + reg:
> + maxItems: 1
> + description: Index of this DSI host among its siblings.
> +
> + status: true
I see slop, I finished here. Mind this maintainers summit words - if you
use AI, you must use good one, not the shloppy slop.
Best regards,
Krzysztof
Hi all,
The goal of this series is to enable userspace driver designs that use
VFIO to export DMABUFs representing subsets of PCI device BARs, and
"vend" those buffers from a primary process to other subordinate
processes by fd. This is achieved by allowing the processes to mmap()
the DMABUFs; their access to the device is isolated to the exported
ranges. The primary userspace driver process can forcibly revoke
access to previously-shared buffers upon cleanup (without requiring
cooperation from the subordinate processes). This is an improvement
on sharing the VFIO device fd to subordinate processes, which would
allow unfettered access. See the RFCs for background.
The existing VFIO PCI BAR mmap() becomes backed by a DMABUF too,
keeping common vm_ops and fault handler for VMAs from the VFIO device
and explicitly-exported DMABUFs. This will help future iommufd
emulation of VFIO Type1 peer-to-peer, making it easier to get a DMABUF
for a VFIO BAR as a DMA target.
Below are per-patch notes & background info, and at the bottom are
several related questions that reviewers may like to consider (worth
at least skipping to #1, a possible bug).
Notes on patches
================
mmap() conversion to use DMABUF underneath has been done for vfio-pci,
but not sub-drivers:
nvgrace-gpu's mmap() override path is unchanged; I kept this out of
scope for now not least because I don't have a thorough test setup for
this system. I would prefer to help the nvgrace-gpu maintainers
enable BAR mmap() DMABUFs themselves.
It's also worth noting that one reason for nvgrace-gpu's special BAR
handling is to map RESMEM with a WC memory type. This is unchanged
for existing mmap() but WC is not currently supported for mapping
DMABUFs exported for that BAR; all DMABUF VMAs currently have the same
memory type and control of UC/WC for a mapping is future work.
vfio/pci: Remove DMABUF export dependency on vdev->memory_lock
In v5 of this series we discover that doing an export from the VFIO
mmap() path (fundamental!) adds a dependency between mmap_lock and
vdev->memory_lock(W) because export was using memory_lock(W) to
protect the vdev->dmabufs list and state within, and a deadlock
scenario leapt out to bite:
https://lore.kernel.org/kvm/9a615f22-c0d4-46ae-9654-db11e94e5fec@ozlabs.org/
The suggestion was to add a dedicated mutex/rwsem specifically for
the DMABUFs/list, which is cleaner than overloading memory_lock(W).
But whilst export could now downgrade to holding memory_lock(R) to
test __vfio_pci_memory_enabled(), a very similar deadlock can still
arise due to a memory_lock(W) elsewhere depending on a prior
memory_lock(R) to be released, and attempting to take
memory_lock(R) will queue behind the (W) for fairness (effectively
an R->R dependency). I'd overlooked that rwsem cannot guarantee
multiple readers.
To be able to export while holding mmap_lock, export cannot hold
memory_lock at all. Instead of testing __vfio_pci_memory_enabled()
(which tracks PCI_COMMAND.MSE and PM state), this patch tracks
device-global DMABUF revocation state in a new vdev->bars_revoked
flag updated by vfio_pci_dma_buf_move(). If an mmap() is somehow
performed during a period when DMABUFs are all revoked, then the
DMABUF is created revoked. Move() already bookends reset, PM
transitions etc., so subsequent revocation state changes work
as-is. This flag is also protected by the dmabuf_lock and thus
memory_lock is not required to export.
vfio/pci: Un-revoke DMABUFs in LOW_POWER_ENTRY_WITH_WAKEUP resume
On LOW_POWER entry, DMABUFs have a move(revoke=true), but the
runtime resume path didn't un-revoke. This adds a corresponding
move(revoke=false), which will later turn into
vfio_pci_unrevoke_bars().
NOTE: the unrevoke is reordered _before_ the eventfd_signal() in
vfio_pci_core_runtime_resume() to remove a window in which a waking
waiter could have observed the DMABUF state as still revoked (or
pm_runtime_engaged = true). (The UAPI docs state the event means
the resume's complete, so observing otherwise seemed unintended.)
Also, when DMABUFs are later mmap()ed, a waiter waking and taking a
fault could have seen the unrevoked state and SIGBUS just before
taking the memory_lock. (If the handler gets to acquire the lock,
though, the resume sequence is complete, and the handler observes
pm_runtime_engaged = false.)
This fix is in this series because the issue will impact CPU access
to the VMA as well (once they use DMABUFs), and so it's a strict
dependency of later commits.
dma-buf: Provide dma_buf_set_name()
Makes dma_buf_set_name() available for use (by helper patch),
taking a kernel-allocated string. The pre-existing local helper
becomes a wrapper copying a __user string for the set-name ioctl.
vfio/pci: Add a helper to look up PFNs for DMABUFs
Adds a DMABUF VMA fault handler helper to determine arbitrary-sized
PFNs from ranges in DMABUF.
vfio/pci: Add a helper to create a DMABUF for a BAR-map VMA
Refactors DMABUF export for use by the existing export feature, and
adds a helper that creates a DMABUF corresponding to a VFIO BAR
mmap() request.
There was a request for decent debug naming in /proc/<pid>/maps
etc. comparable to the existing VFIO names: since the VMAs are
DMABUFs, they have a "dmabuf:" prefix and can't be 100% identical
to before. This is a user-visible change, but this patch at least
now gives us extra info on the BDF & BAR being mmap()ed. The name
is installed with the new dma_buf_set_name() above.
vfio/pci: Convert BAR mmap() to use a DMABUF
The vfio-pci core mmap() creates a DMABUF with the helper above,
and the vm_ops fault handler uses the other helper to resolve the
fault. Because this depends on DMABUF structs/code,
CONFIG_VFIO_PCI_CORE needs to depend on CONFIG_DMA_SHARED_BUFFER.
The CONFIG_VFIO_PCI_DMABUF still conditionally enables the export
support code.
NOTE: The user mmap()s a device fd, but the resulting VMA's vm_file
becomes that of the DMABUF. The DMABUF takes ownership of the
device file and put()s it on release, which maintains the existing
behaviour of a VMA keeping the VFIO device open.
BAR zapping then happens via the existing vfio_pci_dma_buf_move()
path, which now needs to unmap PTEs in the DMABUF's address_space.
NOTE: As local LLM reviews did, Sashiko might falsely worry about
the DMABUF fd being obtained through /proc/pid/map_files and
remapped, but the file is an anon inode and doesn't support the
open op (-ENXIO) so AFAICT this is currently impossible.
NOTE: A side-effect of this is that is_mergeable_vma() will be
false between adjacent mappings of VFIO BARs; merging would require
rebuilding a larger DMABUF representing the union, not just
plugging the VMAs together.
The DMABUF backing the BAR is an implicit/internal export, even
when the CONFIG_VFIO_PCI_DMABUF feature is not included because
CONFIG_PCI_P2PDMA is not available. Without P2PDMA, it's
acceptable for the DMABUF to not have a P2PDMA provider. In this
configuration, the VFIO DMABUF .attach prohibits any import, which
avoids getting as far as a WARN in dma_buf_map_attachment(), which
would fail without P2PDMA anyway.
vfio/pci: Clean up BAR zap and revocation
In general (see NOTE!) the vfio_pci_zap_bars() is now obsolete,
since it unmaps PTEs in the VFIO device address_space which is now
unused. This consolidates all calls (e.g. around reset) with the
neighbouring vfio_pci_dma_buf_move()s into new functions, to
revoke/unrevoke (making the steps clearer).
NOTE: Because drivers can use their own vm_ops and override .mmap,
the core must conservatively assume an overridden .mmap might still
add PTEs to the VFIO device address_space and therefore still does
the zap. A new flag, zap_bars_on_revoke, enables the zap when
.mmap is overridden. A driver that does not need the zap can clear
this to opt-out, e.g. if the driver calls down to the common mmap
(and so uses DMABUFs). hisi-acc-vfio-pci does just this, and thus
sets the opt-out flag.
vfio/pci: Support mmap() of a VFIO DMABUF
Adds mmap() for a DMABUF fd exported from vfio-pci.
It was a goal to keep the VFIO device fd lifetime behaviour
unchanged with respect to the DMABUFs. An application can close
all device fds, and this will revoke/clean up all DMABUFs; then, no
mappings or other access can be performed. When enabling mmap() of
the DMABUFs, this means access through the VMA is also revoked.
This complicates the fault handler because whilst the DMABUF
exists, it has no guarantee that the corresponding VFIO device is
still alive. Adds synchronisation ensuring the vdev is available
before the locks in vdev are touched; this holds the device
registration so that even if the buffer has been cleaned up, vdev
hasn't been freed and so the locks can be safely taken.
vfio/pci: Revoke a DMABUF on request from userspace
This is mostly a rename of `revoked` to an enum, `status`, and
adding a third state for a buffer: usable, revoked temporary,
revoked permanent. A new VFIO feature is added,
VFIO_DEVICE_FEATURE_DMA_BUF_REVOKE, which takes a DMABUF (exported
from the same device) and permanently revokes it. Thus a userspace
driver can guarantee any downstream consumers of a shared fd are
prevented from accessing a BAR range, and that range can be reused.
NOTE: This might block userspace, waiting on importers to detach.
The code doing revocation in vfio_pci_dma_buf_move() is moved, to a
common function used by ..._move() and this new feature.
Testing
=======
(The [RFC ONLY] userspace test program, which drives a QEMU
bochs-display function, can be found in the GitHub branch below. It
at least illustrates how the export, map, revoke, and close semantics
interoperate. WIP on a follow-up with a proper vfio-selftests style
test based on this -- this won't be part of this series.)
This code has been tested in mapping DMABUFs of single/multiple ranges
from multiple BARs, aliasing mmap()s, aliasing ranges across DMABUFs,
vm_pgoff > 0, revocation, shutdown/cleanup scenarios, and hugepage
mappings. No regressions observed on the VFIO selftests, or on our
internal vfio-pci applications. VFIO on i386 has been build-tested.
Thanks to Alex Mastro for building a (WIP) testcase for the
prior mmap_lock->memory_lock issue.
END
===
This is based on v7.3-rc6
These commits are on GitHub for easier browsing, along with
"[RFC ONLY] selftests: vfio: Add standalone vfio_dmabuf_mmap_test":
https://github.com/evansm7/linux/compare/v7.3-rc6...dev/mev/vfio-dmabuf-mma…
Also please see...
https://lore.kernel.org/all/f8efaabd-c06e-4f04-8cfa-489c148e37ba@ozlabs.org/
("[PATCH] dma-buf: Annul dmabuf->file on file release")
...which fixes a stale file pointer issue that could affect VFIO's
DMABUF export. Although the issue exists prior to this series, the
addition of another dmabuf->file dereference adds additional
unpleasant failure modes (for example, unmap_mapping_range() the wrong
file, or good old random data dereference, etc.)
Thanks for reading,
Matt
================================================================================
Changelog:
v8:
- Rebased, on v7.3-rc6
- "dma-buf: Provide dma_buf_set_name()": Comment and "DOC: locking
convention" updates. dma_buf_set_name() is is listed in the "do
not hold resv" category
v7: https://lore.kernel.org/all/20260924152159.49702-1-matt@ozlabs.org/
v6: https://lore.kernel.org/all/20260911214200.33793-1-matt@ozlabs.org/
v5: https://lore.kernel.org/all/20260715174737.15287-1-matt@ozlabs.org/
v4: https://lore.kernel.org/all/20260701171245.90111-1-matt@ozlabs.org/
v3: https://lore.kernel.org/all/20260610154327.37758-1-matt@ozlabs.org/
v2: https://lore.kernel.org/all/20260527102319.100128-1-mattev@meta.com/
v1: https://lore.kernel.org/kvm/20260416131815.2729131-1-mattev@meta.com/
RFCv2: https://lore.kernel.org/kvm/20260312184613.3710705-1-mattev@meta.com/
RFCv1: https://lore.kernel.org/all/20260226202211.929005-1-mattev@meta.com/
Tech topic: https://lore.kernel.org/linux-iommu/20250918214425.2677057-1-amastro@fb.com/
Matt Evans (9):
vfio/pci: Remove DMABUF export dependency on vdev->memory_lock
vfio/pci: Un-revoke DMABUFs in LOW_POWER_ENTRY_WITH_WAKEUP resume
dma-buf: Provide dma_buf_set_name()
vfio/pci: Add a helper to look up PFNs for DMABUFs
vfio/pci: Add a helper to create a DMABUF for a BAR-map VMA
vfio/pci: Convert BAR mmap() to use a DMABUF
vfio/pci: Clean up BAR zap and revocation
vfio/pci: Support mmap() of a VFIO DMABUF
vfio/pci: Revoke a DMABUF on request from userspace
drivers/dma-buf/dma-buf.c | 84 ++-
drivers/vfio/pci/Kconfig | 4 +-
drivers/vfio/pci/Makefile | 3 +-
.../vfio/pci/hisilicon/hisi_acc_vfio_pci.c | 14 +-
drivers/vfio/pci/vfio_pci_config.c | 30 +-
drivers/vfio/pci/vfio_pci_core.c | 222 +++++--
drivers/vfio/pci/vfio_pci_dmabuf.c | 609 +++++++++++++++---
drivers/vfio/pci/vfio_pci_priv.h | 54 +-
include/linux/dma-buf.h | 16 +-
include/linux/vfio_pci_core.h | 3 +
include/uapi/linux/vfio.h | 24 +
11 files changed, 870 insertions(+), 193 deletions(-)
--
2.47.3
On Wed, Oct 14, 2026 at 12:02:02PM +0100, Pavel Begunkov wrote:
> Premapped buffers don't require a generic bio_vec since these have
> already been dma mapped. Repurpose the bi_io_vec space to store dmabuf
> maps as they are mutually exclusive.
>
> The bio splitting differs from the normal path because it's already
> pre-mapped and for the block layer it's just an offset into the dma-buf.
> The actual segmentation is only available to the importer driver and not
> the block layer, however, it doesn't contain alignment gaps and we don't
> have to check it. For the same reason we can't precisely split by the
> number of segments, but we use ->min_seg_shift stored in the map to
> calculate the minimum number of bytes a request consisting of
> lim->max_segments full segments can cover and split by that. It's
> stricter and can add extra splitting. E.g. for a {4K, 4G} segmentation,
> the min segment size is 4K, and we'll split it into bios of
> (4K * lim->max_segments) bytes each, but it should be good enough for
> now to cover the most popular use cases.
>
> Suggested-by: Keith Busch <kbusch(a)kernel.org>
> Signed-off-by: Pavel Begunkov <asml.silence(a)gmail.com>
> ---
> block/bio.c | 15 +++++++++--
> block/blk-merge.c | 52 +++++++++++++++++++++++++++++++++++++++
> block/blk-mq.c | 6 +++++
> block/fops.c | 2 +-
> include/linux/bio.h | 9 ++++---
> include/linux/blk-mq.h | 7 ++++++
> include/linux/blk_types.h | 14 ++++++++++-
> include/linux/bvec.h | 3 ++-
> 8 files changed, 99 insertions(+), 9 deletions(-)
>
> diff --git a/block/bio.c b/block/bio.c
> index b48091c7663f..1e0d9714c541 100644
> --- a/block/bio.c
> +++ b/block/bio.c
> @@ -881,7 +881,11 @@ static int __bio_clone(struct bio *bio, struct bio *bio_src, gfp_t gfp)
> bio->bi_write_stream = bio_src->bi_write_stream;
> bio->bi_bvec_gap_bit = bio_src->bi_bvec_gap_bit;
> bio->bi_iter = bio_src->bi_iter;
> - bio->bi_io_vec = bio_src->bi_io_vec;
> +
> + if (op_is_dmabuf(bio->bi_opf))
> + bio->bi_dmabuf_map = bio_src->bi_dmabuf_map;
> + else
> + bio->bi_io_vec = bio_src->bi_io_vec;
>
> if (bio->bi_bdev) {
> if (bio->bi_bdev == bio_src->bi_bdev &&
> @@ -1204,16 +1208,23 @@ EXPORT_SYMBOL_GPL(__bio_release_pages);
>
> bool bio_iov_iter_set(struct bio *bio, const struct iov_iter *iter)
> {
> - if (!iov_iter_is_bvec(iter))
> + if (!iov_iter_is_bvec(iter) && !iov_iter_is_dmabuf_map(iter))
> return false;
>
> WARN_ON_ONCE(bio->bi_max_vecs);
>
> + static_assert(offsetof(struct bio, bi_io_vec) ==
> + offsetof(struct bio, bi_dmabuf_map));
> + static_assert(offsetof(struct iov_iter, bvec) ==
> + offsetof(struct iov_iter, dmabuf_map));
> +
> bio->bi_io_vec = (struct bio_vec *)iter->bvec;
> bio->bi_iter.bi_idx = 0;
> bio->bi_iter.bi_offset = iter->iov_offset;
> bio->bi_iter.bi_size = iov_iter_count(iter);
> bio_set_flag(bio, BIO_CLONED);
> + if (iov_iter_is_dmabuf_map(iter))
> + bio->bi_opf |= REQ_NOMERGE | REQ_DMABUF;
> return true;
> }
>
> diff --git a/block/blk-merge.c b/block/blk-merge.c
> index 258a726071d1..501ddc01c449 100644
> --- a/block/blk-merge.c
> +++ b/block/blk-merge.c
> @@ -9,6 +9,7 @@
> #include <linux/blk-integrity.h>
> #include <linux/part_stat.h>
> #include <linux/blk-cgroup.h>
> +#include <linux/dma-buf-io.h>
>
> #include <trace/events/block.h>
>
> @@ -319,6 +320,41 @@ static inline unsigned int bvec_seg_gap(struct bio_vec *bvprv,
> return bv->bv_offset | (bvprv->bv_offset + bvprv->bv_len);
> }
>
> +static inline int bio_split_io_at_dmabuf(struct bio *bio,
> + const struct queue_limits *lim, unsigned *segs,
> + unsigned max_bytes, unsigned len_align_mask,
> + unsigned start_align_mask)
> +{
> + unsigned bytes = min(bio->bi_iter.bi_size, max_bytes);
> + unsigned seg_shift = bio->bi_dmabuf_map->min_seg_shift;
> + unsigned offset = bio->bi_iter.bi_offset & ((1U << seg_shift) - 1);
> + u64 max_segs_bytes;
> +
> + /*
> + * dma-buf maps don't expose the underlying segmentation, but they're
> + * guaranteed to not have alignment gaps, we only need to check the
> + * start and length alignment.
> + */
> + if ((bio->bi_iter.bi_offset & start_align_mask) ||
> + (bio->bi_iter.bi_size & len_align_mask))
> + return -EINVAL;
> +
> + /* Presented as a single contiguous range into the dma-buf */
> + *segs = 1;
> +
> + /*
> + * Limit by the number of segments by using the minimal segment size.
> + * Any I/O consisting of N full segments should be able to cover at
> + * least N multiplied by the segment size. It's stricter than walking
> + * the segments and might cause extra splitting.
> + */
> + max_segs_bytes = (u64)lim->max_segments << seg_shift;
> + bytes = min_t(u64, bytes, max_segs_bytes - offset);
> + if (bytes != bio->bi_iter.bi_size)
> + return bytes;
> + return 0;
> +}
> +
> /**
> * bio_split_io_at - check if and where to split a bio
> * @bio: [in] bio to be split
> @@ -346,6 +382,19 @@ int bio_split_io_at(struct bio *bio, const struct queue_limits *lim,
> len_align_mask |= (bc->bc_key->crypto_cfg.data_unit_size - 1);
> }
>
> + if (op_is_dmabuf(bio->bi_opf)) {
> + int ret;
> +
> + ret = bio_split_io_at_dmabuf(bio, lim, &nsegs, max_bytes,
> + len_align_mask, start_align_mask);
> + if (ret < 0)
> + return ret;
> + if (!ret)
> + goto out;
> + bytes = ret;
> + goto split;
> + }
> +
> bio_for_each_bvec(bv, bio, iter) {
> if (bv.bv_offset & start_align_mask ||
> bv.bv_len & len_align_mask)
> @@ -376,6 +425,7 @@ int bio_split_io_at(struct bio *bio, const struct queue_limits *lim,
> bvprvp = &bvprv;
> }
>
> +out:
> *segs = nsegs;
> bio->bi_bvec_gap_bit = ffs(gaps);
> return 0;
> @@ -493,6 +543,8 @@ unsigned int blk_recalc_rq_segments(struct request *rq)
>
> if (!rq->bio)
> return 0;
> + if (op_is_dmabuf(rq->bio->bi_opf))
> + return 1;
>
> switch (bio_op(rq->bio)) {
> case REQ_OP_DISCARD:
> diff --git a/block/blk-mq.c b/block/blk-mq.c
> index e929f94b25c7..1b7f8cbbda8b 100644
> --- a/block/blk-mq.c
> +++ b/block/blk-mq.c
> @@ -3150,6 +3150,12 @@ void blk_mq_submit_bio(struct bio *bio)
> goto queue_exit;
> }
>
> + if (unlikely(op_is_dmabuf(bio->bi_opf) &&
> + bdev_has_integrity_csum(bio->bi_bdev))) {
> + bio_endio_status(bio, BLK_STS_NOTSUPP);
Wrong indentation, conditions are never indented the same level as
the following code block, even with the weirdest preferences.
/me note the patch from Anuj on the list actually got this right..
Otherwise looks good:
Reviewed-by: Christoph Hellwig <hch(a)lst.de>