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
Adding T.J. to comment.
Regards,
Christian.
On 11/10/26 13:51, Kang Chen wrote:
> bpf_iter_dmabuf_next() uses kit->dmabuf == NULL to mean "iteration has
> not started". dma_buf_iter_next() also returns NULL at the end of the
> list, so a next() call after exhaustion restarts from the list head.
>
> The verifier relies on the iterator contract that once next() returns
> NULL it keeps returning NULL: process_iter_next_call() marks the
> iterator DRAINED and treats the result of later next() calls as the
> constant zero. A restarted dmabuf iteration therefore hands the BPF
> program a kernel pointer while the verifier believes R0 == 0.
>
> Use an invalid pointer value as the drained sentinel so the iterator
> state keeps its one-pointer ABI, and skip dma_buf_put() for it.
>
> Fixes: 6eab7ac7c5ee ("bpf: Add open coded dmabuf iterator")
> Signed-off-by: Kang Chen <k.chen(a)smail.nju.edu.cn>
> ---
> kernel/bpf/dmabuf_iter.c | 23 ++++++++++++++++++++++-
> 1 file changed, 22 insertions(+), 1 deletion(-)
>
> diff --git a/kernel/bpf/dmabuf_iter.c b/kernel/bpf/dmabuf_iter.c
> index cd500248abd9..a2b7c38f9ae6 100644
> --- a/kernel/bpf/dmabuf_iter.c
> +++ b/kernel/bpf/dmabuf_iter.c
> @@ -156,6 +156,13 @@ struct bpf_iter_dmabuf_kern {
> struct dma_buf *dmabuf;
> } __aligned(8);
>
> +/*
> + * The iterator state is one pointer wide because struct bpf_iter_dmabuf is
> + * part of the generated vmlinux.h ABI. Use an invalid pointer value as the
> + * "drained" sentinel instead of growing the state.
> + */
> +#define DMABUF_ITER_DONE ((struct dma_buf *)1L)
> +
> __bpf_kfunc_start_defs();
>
> __bpf_kfunc int bpf_iter_dmabuf_new(struct bpf_iter_dmabuf *it)
> @@ -173,11 +180,25 @@ __bpf_kfunc struct dma_buf *bpf_iter_dmabuf_next(struct bpf_iter_dmabuf *it)
> {
> struct bpf_iter_dmabuf_kern *kit = (void *)it;
>
> + /*
> + * The verifier assumes that an iterator which returned NULL keeps
> + * returning NULL (see process_iter_next_call()). Without this check
> + * the NULL left by the last dma_buf_iter_next() would be interpreted
> + * as "not started" and the iteration would restart from the list head.
> + */
> + if (kit->dmabuf == DMABUF_ITER_DONE)
> + return NULL;
> +
> if (kit->dmabuf)
> kit->dmabuf = dma_buf_iter_next(kit->dmabuf);
> else
> kit->dmabuf = dma_buf_iter_begin();
>
> + if (!kit->dmabuf) {
> + kit->dmabuf = DMABUF_ITER_DONE;
> + return NULL;
> + }
> +
> return kit->dmabuf;
> }
>
> @@ -185,7 +206,7 @@ __bpf_kfunc void bpf_iter_dmabuf_destroy(struct bpf_iter_dmabuf *it)
> {
> struct bpf_iter_dmabuf_kern *kit = (void *)it;
>
> - if (kit->dmabuf)
> + if (kit->dmabuf && kit->dmabuf != DMABUF_ITER_DONE)
> dma_buf_put(kit->dmabuf);
> }
>
> --
> 2.34.1
>
On 11/6/26 14:18, Tao Cui wrote:
> From: Tao Cui <cuitao(a)kylinos.cn>
>
> udmabuf pins the pages of a memfd and hands them out as a dma-buf. The
> data pages keep the accounting of the memfd they were instantiated in,
> but the bookkeeping around them does not: the page pointer array and
> the pinned_folios array, both sized by the buffer page count, plus the
> transient folios array sized by the memfd folio count, are plain
> GFP_KERNEL. A 1GB buffer costs about 4MB of uncharged SUnreclaim
> memory, and size_limit_mb defaults to INT_MAX.
>
> Charge the three kvmalloc allocations so the creator pays for the
> metadata it induces. The system heap in the same subsystem already
> accounts its buffer allocation; the data pages here stay with the
> memfd.
T.J. needs to take a look here, but I fear that this might break uAPI.
A lot of the DMA-buf resources are intentionally not charged against memcg.
Regards,
Christian.
>
> Signed-off-by: Tao Cui <cuitao(a)kylinos.cn>
> ---
> drivers/dma-buf/udmabuf.c | 7 ++++---
> 1 file changed, 4 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/dma-buf/udmabuf.c b/drivers/dma-buf/udmabuf.c
> index df6dd0046242..40182c82df6b 100644
> --- a/drivers/dma-buf/udmabuf.c
> +++ b/drivers/dma-buf/udmabuf.c
> @@ -190,11 +190,12 @@ static void unpin_all_folios(struct udmabuf *ubuf)
>
> static __always_inline int init_udmabuf(struct udmabuf *ubuf, pgoff_t pgcnt)
> {
> - ubuf->pages = kvmalloc_objs(*ubuf->pages, pgcnt);
> + ubuf->pages = kvmalloc_objs(*ubuf->pages, pgcnt, GFP_KERNEL_ACCOUNT);
> if (!ubuf->pages)
> return -ENOMEM;
>
> - ubuf->pinned_folios = kvmalloc_objs(*ubuf->pinned_folios, pgcnt);
> + ubuf->pinned_folios = kvmalloc_objs(*ubuf->pinned_folios, pgcnt,
> + GFP_KERNEL_ACCOUNT);
> if (!ubuf->pinned_folios)
> return -ENOMEM;
>
> @@ -387,7 +388,7 @@ static long udmabuf_create(struct miscdevice *device,
> if (ret)
> goto err;
>
> - folios = kvmalloc_objs(*folios, max_nr_folios);
> + folios = kvmalloc_objs(*folios, max_nr_folios, GFP_KERNEL_ACCOUNT);
> if (!folios) {
> ret = -ENOMEM;
> goto err;
> --
> 2.43.0
>
Write permissions on the /dev/dma_heap/* device files are not required
to issue ioctls and allocate dmabufs. Applications should be opening
these file as O_RDONLY. The BPF dmabuf_iter selftest already does
this. [1]
Users are pointing to these selftests as examples of how use dmabuf,
and encountering permission errors on systems where write permissions
are not available on /dev/dma_heap/*. Apply the principle of least
privilege to selftests which open dmabuf heaps by removing the write
access mode and using O_RDONLY for the open() instead.
The same is true for the vgem test using /dev/dri/card.
[1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/too…
Signed-off-by: T.J. Mercier <tjmercier(a)google.com>
---
tools/testing/selftests/dmabuf-heaps/dmabuf-heap.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/tools/testing/selftests/dmabuf-heaps/dmabuf-heap.c b/tools/testing/selftests/dmabuf-heaps/dmabuf-heap.c
index fc9694fc4e89..45b420e37c97 100644
--- a/tools/testing/selftests/dmabuf-heaps/dmabuf-heap.c
+++ b/tools/testing/selftests/dmabuf-heaps/dmabuf-heap.c
@@ -48,7 +48,7 @@ static int open_vgem(void)
snprintf(name, 80, "%s%u", drmstr, i);
- fd = open(name, O_RDWR);
+ fd = open(name, O_RDONLY);
if (fd < 0)
continue;
@@ -96,7 +96,7 @@ static int dmabuf_heap_open(char *name)
if (ret < 0)
ksft_exit_fail_msg("snprintf failed! %d\n", ret);
- fd = open(buf, O_RDWR);
+ fd = open(buf, O_RDONLY);
if (fd < 0)
ksft_exit_fail_msg("open %s failed: %s\n", buf, strerror(errno));
base-commit: 9a11db68872055e6ead919bad04d6330851c522d
--
2.55.0.679.g6767b8d81c-goog
On 11/9/26 03:58, Alistair Popple wrote:
> On 2026-11-07 at 19:57 +1100, Karl Mehltretter <kmehltretter(a)gmail.com> wrote...
>> On Thu, Nov 05, 2026 at 05:40:41PM +0100, Alistair Popple wrote:
>>> + * A pin or map that fails after dma_buf_mapping_select() may reopen the
>>> + * choice only if it was the one that made it. A selection that predates the
>>> + * call belongs to a live pin or mapping and must survive, otherwise the next
>>> + * pin or map would reselect under it without an invalidate.
>>> + */
>>> +void dma_buf_mapping_unselect(struct dma_buf_attachment *attach,
>>> + bool was_selected)
>>> +{
>>> + dma_resv_assert_held(attach->dmabuf->resv);
>>> +
>>> + if (was_selected)
>>> + return;
>>> +
>>> + attach->selected = false;
>>> + attach->selected_idx = 0;
>>> +}
>>> +
>>
>> After dma_buf_invalidate_mappings(), attach->selected is false while
>> attach->selected_idx still holds that mapping's entry for a pending
>> unmap.
>>
>> If a pin/map fails before that unmap runs, was_selected is false and
>> dma_buf_mapping_unselect() resets attach->selected_idx to 0.
>>
>> A subsequent dma_buf_unmap_sgt() then uses matches[0].
>
> Actually there's a bigger issue here. The contract at the moment states that
> mapping type may change after invalidation. However that doesn't account for the
> fact mappings can outlive the invalidation.
>
> This could be dealt with by switching everything over to the generic
> dma_buf_mapping_map/unmap() path, but that requires an allocation per mapping
> just to track the mapping type.
You need an allocation per mapping anyway to identify the mapping anyway.
We currently abuse the sg_table for that, but essentially the idea of having a structure/object to represent the mapping needs to stay around as far as I can see.
Regards,
Christian.
>
> The alternate is we update the contract to say mapping type cannot change until
> after all importers have unmapped. Enforcing this would require tracking the
> number of live mappings/pins per-attachment, but I think this is the better
> solution so will add that for the next version.
>
>>> int dma_buf_pin(struct dma_buf_attachment *attach)
>>> {
>>> struct dma_buf *dmabuf = attach->dmabuf;
>>> + bool selected = attach->selected;
>>> int ret = 0;
>>>
>>> WARN_ON(!attach->importer_ops);
>>>
>>> dma_resv_assert_held(dmabuf->resv);
>>>
>>> - if (dmabuf->ops->pin)
>>> + ret = dma_buf_mapping_select(attach);
>>> + if (ret)
>>> + return ret;
>>> +
>>> + if (dmabuf->ops->pin) {
>>> ret = dmabuf->ops->pin(attach);
>>> + if (ret)
>>> + dma_buf_mapping_unselect(attach, selected);
>>> + }
>>
>> dma_buf_mapping_select() sets attach->selected = true before ops->pin()
>> and the map callbacks run.
>>
>> In patches 14/15, xe/amdgpu migrate a VRAM buffer to system memory
>> during pin and map when the attachment does not accept P2P.
>>
>> That migration calls dma_buf_invalidate_mappings() and clears
>> attach->selected on every attachment, also the one being pinned/mapped.
>>
>> When the callback succeeds, the attachment stays pinned or mapped with
>> attach->selected == false.
>>
>> A later map/pin on the same attachment can then reselect without an
>> invalidation.
>
> Argh. Thanks. Will fix.
>
> - Alistair
>
>> Thanks,
>> Karl
Hi Karl,
We discussed in v1 how this is not the right approach. Why are you
posting a v2 without addressing that ? You need to go back to the design
table.
On Sat, Nov 07, 2026 at 11:47:00AM +0100, Karl Mehltretter wrote:
> uvcvideo and vivid (when using vb2-vmalloc) access imported DMA-BUFs
> through a kernel vmap without cache synchronization. When a non-coherent
> importer such as V3D maps the same DMA-BUF persistently, captured data
> remains in the CPU cache while physical RAM holds stale bytes.
>
> Add an opt-in uses_cpu_access queue flag for vb2-vmalloc queues to
> bracket the interval from buf_prepare() through buf_finish() with
> dma_buf_begin_cpu_access() and dma_buf_end_cpu_access(). Keep this
> opt-in because some vb2-vmalloc drivers pass imported buffers to
> hardware, and end CPU access in process context because DMA-BUF
> callbacks may sleep.
>
> This follows the per-queue flag proposed here:
> https://lore.kernel.org/r/CAAFQd5Am5jBev5P1HmsdeHoJfROZat3bi1W=UsN7wpVqw-XU…
>
> Based on Linux 7.4-rc1 with prerequisite patch "media: videobuf2: finish
> prepared buffers in VIDIOC_REMOVE_BUFS":
> https://lore.kernel.org/r/20261026071735.37220-1-kmehltretter@gmail.com/
>
> Changes in v2:
> - Split patch 1 of v1 into the standalone VIDIOC_REMOVE_BUFS patch above
> and use its __vb2_buf_cancel() helper so queue cancellation and
> VIDIOC_REMOVE_BUFS share the finish path (Tomasz).
> - Scope uses_cpu_access to vb2-vmalloc queues and drop the attach_dmabuf
> dma_dir parameter from vb2_mem_ops, videobuf2-dma-contig,
> videobuf2-dma-sg and videobuf2-vmalloc (Tomasz).
> - Enable uses_cpu_access in vivid only when vivid uses
> vb2_vmalloc_memops (Tomasz).
>
> Link to v1:
> https://lore.kernel.org/r/cover.1792392288.git.kmehltretter@gmail.com/
>
> Testing:
>
> - Raspberry Pi 500+ (6.18.34+rpt-rpi-2712, aarch64, 16 KiB pages,
> Sunplus UVC camera 1bcf:2701 and Broadcom V3D 7.1 GPU), backport of
> the prerequisite patch plus patches 1 and 2: eight 640x480 YUYV frames
> (614,400 B) captured into DMA-BUFs pre-seeded with 0xA5 and imported
> into persistent EGL_LINUX_DMA_BUF_EXT textures before VIDIOC_STREAMON,
> then copied by V3D 7.1 immediately after VIDIOC_DQBUF:
>
> Heap Baseline stale Patched v2 stale
> /dev/dma_heap/linux,cma 8/8 (329,890 B) 0/8 (0 B)
> /dev/dma_heap/system 8/8 (509,818 B) 0/8 (0 B)
>
> - QEMU virt (arm64, Linux 7.4-rc1 with the prerequisite patch and
> patches 1-3, VIDEO_ADV_DEBUG=y, DEBUG_ATOMIC_SLEEP=y): six vivid
> lifecycle cases (stream, streamoff-queued, prepare-reqbufs0,
> prepare-remove, close-streaming, replace-dmabuf) across single-planar
> and multi-planar queues with kprobe counters on
> dma_buf_begin_cpu_access() and dma_buf_end_cpu_access():
>
> Queue begin/end calls Unbalanced Warnings
> vivid vb2-vmalloc (SP) 34 / 34 0 0
> vivid vb2-vmalloc (MP) 34 / 34 0 0
> vivid vb2-dma-contig (SP) 0 / 0 0 0
> vivid vb2-dma-contig (MP) 0 / 0 0 0
> 20x prepare-remove (vmalloc) 20 / 20 0 0
>
> Assisted by an LLM for code changes, test harnesses and commit message
> drafting.
>
> Karl Mehltretter (3):
> 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 | 76 +++++++++++++++++++
> drivers/media/test-drivers/vivid/vivid-core.c | 4 +-
> drivers/media/usb/uvc/uvc_queue.c | 1 +
> include/media/videobuf2-core.h | 5 ++
> 4 files changed, 85 insertions(+), 1 deletion(-)
>
>
> base-commit: 6628e7d4c6b25c8d18f1345e3a20d21829aae7e4
> prerequisite-patch-id: aa99d5c3c27082cbe003ed94a195e3de415777c9
> --
> 2.39.5 (Apple Git-154)
--
Regards,
Laurent Pinchart
Marc Zyngier <maz(a)kernel.org> writes:
> On Wed, 04 Nov 2026 16:45:55 +0000,
> "Aneesh Kumar K.V (Arm)" <aneesh.kumar(a)kernel.org> wrote:
>>
>> VPE L1 tables are allocated from the CPU-starting callback, where sleeping is
>> not allowed. Remove the page allocation from this atomic path.
>>
>> Use a blocking allocation for the boot CPU and record the resulting table
>> order. Allocate a page of that order from the sleepable CPU hotplug prepare
>> stage for each secondary CPU. Consume the preallocated page only when the CPU
>> cannot inherit an existing redistributor or ITS table.
>>
>> Reclaim unused preallocations after the CPU reaches the online state, and from
>> the prepare-state teardown when CPU bring-up aborts.
>
> No. The way to do it is to move the ITS probing out of the
> non-sleepable CPU hotplug path.
>
> I proposed a potential hack at [1] (which I find far more palatable
> than this proposal), but the real fix is to probe the ITSs as
> devices.
>
Could you share a bit more detail on what you have in mind?
Are you suggesting that we create a platform device for each ITS and
initialize it through the driver's probe callback, while the rest of the
GIC initialization stays in the existing early boot path?
Would that mean the main GIC is operational during early boot, while
ITS-dependent features, such as MSI delivery and direct injection, become
available after the ITS devices probe?
Is that the split you have in mind?
-aneesh
Suzuki K Poulose <suzuki.poulose(a)arm.com> writes:
> On 04/11/2026 16:45, Aneesh Kumar K.V (Arm) wrote:
>> Confidential-computing guests may require memory shared with the host to
>> be aligned and transitioned in units larger than PAGE_SIZE. Several DMA
>> users need struct page-backed allocations satisfying these requirements.
>> Provide a common allocator instead of requiring each user to open-code
>> this sequence.
>>
>> Add alloc_cc_shared_pages() and its node-aware variant. The allocator
>> rounds the requested size to the architecture's shared granule,
>> allocates suitably aligned contiguous pages and transitions the
>> complete range to shared state. It also preserves the caller's GFP
>> policy.
>>
>> A private-to-shared transition may alter memory contents. Mask
>> __GFP_ZERO from the underlying allocation and when requested, clear the
>> complete transitioned range after cc_make_shared() succeeds.
>
> This is not true for pKVM though. It is the other way around. i.e,
> pages must be cleared before transition (e.g., from private to shared)
> to make sure the contents don't leak into the host.
>
> Do we need to handle such cases with a pre_conversion and
> post_conversion hook ?
>
Patch 2 does something similar.
-aneesh