On Wed, 2026-07-15 at 15:57 -0300, Daniel Almeida wrote:
> Hi Phillipp,
Hello, thx for the review
>
> >
[…]
> > new file mode 100644
> > index 000000000000..cbe8f447a603
> > --- /dev/null
> > +++ b/rust/kernel/dma_buf/dma_fence.rs
> > @@ -0,0 +1,894 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +//
> > +// Copyright (T) 2025, 2026 Red Hat Inc.:
> > +// - Philipp Stanner <pstanner(a)redhat.com>
>
> SPDX-copyrightText?
ACK.
>
> > +
> > +//! DriverFence support.
>
> This contains, Fence, DriverFence and FenceContext, along with other
> miscellaneous. I would spend a bit more time fleshing this out slightly.
OK.
>
> > +//!
> > +//! Reference: <https://docs.kernel.org/driver-api/dma-buf.html#c.dma_fence>
> > +//!
> > +//! T header: [`include/linux/dma-fence.h`](srctree/include/linux/dma-fence.h)
>
> T?
Relic. Will fix.
>
> > +
> > +
[…]
> > + try_pin_init!(Self {
> > + // SAFETY: `dma_fence_context_alloc()` merely works on a global atomic.
> > + // Parameter `1` is the number of contexts we want to allocate.
> > + nr: unsafe { bindings::dma_fence_context_alloc(1) },
> > + seqno: AtomicU64::new(0),
>
> Do we really need to force a 0 here? i.e.: can’t we take the initial seqno
> as an argument?
We could. What would that be useful for?
>
> > + driver_name,
> > + timeline_name,
> > + data <- data,
> > + })
> > + }
> > +
> >
[…]
> > + /// Create a new fence, consuming `data`.
> > + ///
> > + /// The fence will increment the refcount of the fence context associated with this
> > + /// [`FenceCtx`].
> > + pub fn new_fence(&self, memory: DriverFenceAllocation<'a, T>) -> DriverFence<'a, T> {
>
> Do we ever check if the allocation was really made by “self” ? Apparently not :/
Hm, no, we don't.
For the most part that's irrelevant, since all critical components then
only get set in new_fence(). Correct typization is enforced through T.
The notable exception is the fence_ctx reference itself.
What should we do about it?
We could keep the fctx field as a MaybeUninit and set it later. Or we
check through the fctx identifier number whether it's the correct one
in new_fence(), but then new_fence() could fail with some error, and
it's probably better to have it be completely fail-free.
>
> >
[…]
> > +pub trait FenceCb: Send + 'static {
>
> IMHO these acronyms make the code harder to read for no gain. I don’t think
> we have to carry that over from C.
>
> FenceCb -> FenceCallback
No principle objections from me. But do you believe *all* of them are
bad? I really like `let fctx = …` for instance.
>
> > + /// Called when the fence is signaled.
> > + ///
> > + /// This is called from the fence signaling path, which may be in interrupt
> > + /// context or with locks held, which is why `self` is only borrowed, so that
> > + /// it cannot drop. Implementations must not sleep or perform
> > + /// long-running operations.
> > + ///
> > + /// An implementation likely wants to inform itself (e.g., through a work item)
> > + /// within this callback that the associated [`FenceCbRegistration`] can now be
> > + /// dropped.
> > + fn called(&mut self);
>
> I think “signaled” is more descriptive than “called”.
Here I disagree. A callback does not get signaled. It gets called once
the fence gets signaled.
>
> > +}
> > +
> >
[…]
> > +
> > +/// The receiving counterpart of a [`DriverFence`], designed to register callbacks
> > +/// on, check the signalled state etc. A [`Fence`] cannot be signalled.
> > +/// A [`Fence`] is always refcounted.
>
> I would explain this a tad better.
What exactly? The refcounting? The dualism between DriverFence and
Fence? :)
>
> > +#[repr(transparent)]
> > +pub struct Fence {
> > + /// The actual dma_fence passed to C.
> > + inner: Opaque<bindings::dma_fence>,
> > +}
> > +
> > +// SAFETY: Fences are literally designed to be shared between threads.
> > +unsafe impl Send for Fence {}
> > +// SAFETY: Fences are literally designed to be shared between threads.
> > +unsafe impl Sync for Fence {}
> > +
> > +impl Fence {
> > + /// Check whether the fence was signalled at the moment of the function call.
> > + ///
> > + /// Note that this can return `true` for a [`Fence`] whose [`DriverFence`]
> > + /// has not yet been dropped. The reason is that the fence ops callbacks can
> > + /// cause the fence to get signaled by the C backend.
> > + pub fn is_signaled(&self) -> bool {
> > + let fence = self.as_raw();
> > + let mut fence_flags: usize = 0;
> > + let flag_ptr = &raw mut fence_flags;
> > +
> > + // We shouuld not use `dma_fence_is_signaled_locked()` here, because
>
> typo
ACK.
>
> > + // according to the C backend's recommendations, that function is problematic
> > + // and we should avoid calling that function with a lock held.
> > +
> > + // SAFETY: `self` is valid by definition. We take the spinlock above.
>
> Where?
The safety comment is wrong / outdated. See below.
>
> > + let ret = unsafe { bindings::dma_fence_is_signaled(fence) };
> > +
> > + // To guarantee that an API caller can 100% rely on the signalling being
> > + // completed (i.e., all fence callbacks ran), we have to take the lock.
> > + //
> > + // The reason is that the C dma_fence backend currently does not carefully
> > + // synchronize the `dma_fence_is_signaled()` function with the proper
> > + // spinlock. This can lead to the function returning `true` while fence
> > + // callbacks are still being executed. This can be mitigated by guarding
> > + // the entire function with the spinlock.
> > + //
> > + // See commit c8a5d5ea3ba6a.
> > +
> > + // SAFETY: `fence` is valid because `self` is valid. `flag_ptr` is
> > + // merely a pointer to an integer, which lives as long as this function.
> > + unsafe { bindings::dma_fence_lock_irqsave(fence, flag_ptr) };
>
> Shouldn’t this be before the “is_signaled” ffi call? Or is this
> only about ensuring all callbacks have run? i.e.: is “ret” valid even
> though it was computed before taking the lock?
OK, this is where it gets ugly.
So during the last weeks I've been struggling to get the C backend into
better shape. One issue from my POV is that the C dma_fence spinlock
does not protect the fence state; there is insistence that the lock
shall only protect the callback list.
The function dma_fence_is_signaled() has an unlocked fast path check:
https://elixir.bootlin.com/linux/v7.2-rc3/source/include/linux/dma-fence.h#…
whereas setting of that bit is done under lock-protection:
https://elixir.bootlin.com/linux/v7.2-rc3/source/drivers/dma-buf/dma-fence.…
This can lead to funny races like in the commit mentioned in the
comment block above (c8a5d5ea3ba6a).
And it also leads to weird hacks like this:
https://elixir.bootlin.com/linux/v7.2-rc3/source/drivers/gpu/drm/amd/amdgpu…
Now, in principle I agree with you that a pattern like this:
dma_fence_lock_irqsave(…);
let signaled = dma_fence_is_signaled_locked(…);
dma_fence_unlock_irqrestore(…);
would be better.
However, lengthy discussions with Christian seem to settle at the point
where Christian sees the very strict requirement of never calling fence
callbacks under lock protection, and where he views
dma_fence_is_signaled_locked() as a broken function that should be
removed.
He's currently working on removing all bits where fence callbacks are
invoked under lock protection:
https://lore.kernel.org/dri-devel/20260624122917.2483-1-christian.koenig@am…
There's been a ton of discussions and proposals about that in recent
weeks
https://lore.kernel.org/dri-devel/20260608142436.265820-2-phasta@kernel.org/https://lore.kernel.org/dri-devel/20260612104251.2264707-2-phasta@kernel.or…
So tl;dr: The weird code you're commenting on above ensures that
a) the fence->ops->is_signaled() callback is not called under lock
protection and
b) taking and releasing the lock guarantees that all callbacks are
really finished, i.e. they have run.
(I continue to believe that setting the bit under lock protection and
reading it without lock is fundamentally broken and needs to be fixed,
but fixes are being rejected because of claimed performance regressions
years ago when this was tried, because checking the bit is some sort of
fast path check for.. parties that spin on dma_fence_is_signaled() ??)
>
> >
[…]
> > +}
> > +// Necessary to guarantee that `inner` always comes first and can be freed by C.
> > +// Also useful for using casts instead of container_of().
> > +#[repr(C)]
> > +#[pin_data]
> > +struct DriverFenceData<'a, T: Send + Sync + FenceCtxOps> {
> > + #[pin]
> > + /// The inner fence.
> > + // Must always be the first member so that unsafe casting works; but also
> > + // necessary so that the C backend can free the allocation (coming from our
> > + // Rust code) with kfree_rcu().
> > + inner: Fence,
> > + /// Callback head for dropping this in a deferred manner through RCU.
> > + rcu_head: bindings::callback_head,
> > + /// Reference to access the FenceCtx. Useful for obtaining name parameters.
> > + fctx: &'a FenceCtx<T>,
>
> This creates a self-referential borrow in the JobQueue, since it holds both (a) the
> context to mint new seqnos from and (b) the xarray with fences which borrow from
> that same context. This issue does not exist with the Arc and we should really
> fix it before moving with this series.
Can you detail that a bit more. So your JobQueue version has a `data:
T` where T holds both the xarray and a jobqueue. The xarray contains
fences that hold references to the FenceCtx. But shouldn't that be fine
since the life time ensures that the drop order is correct?
btw we are recently coming up with a proposal on how JobQueue could
store DriverFences for the driver. I want to present some RFC for that
soonish.
>
>
> > + /// The API user's data. This must either not need drop, or must delay its
> > + /// drop by a grace period. It is essential that the data only performs
> > + /// operations legal in atomic context in its [`Drop`] implementation.
> > + #[pin]
> > + data: T::FenceDataType,
> > +}
> > +
> >
[…]
> > +
> > + // DriverFenceData is repr(C) and a Fence is its first member.
>
> > + let fence_data_ptr = fence_ptr as *mut DriverFenceData<'a, T>;
>
> Without a “CAST:” keyword, I think this will trigger the linter?
>
Didn't see a complaint from clippy nor compiler.
>
> > +
> >
[…]
>
> lifetime is a single word.
ACK.
>
> > +}
> > +
> > +impl<'a, T: Send + Sync + FenceCtxOps> Deref for DriverFenceBorrow<'a, T> {
> > + type Target = DriverFence<'a, T>;
> > +
> > + fn deref(&self) -> &Self::Target {
> > + self.driver_fence.deref()
> > + }
> > +}
> > +
> > +// SAFETY: The Rust dma_fence abstractions are already designed around the inner
> > +// C `dma_fence`, which can serve safely as the identification point when being
> > +// owned by C. Moreover, safety is ensured by not dropping `DriverFence` and by
> > +// only allowing operations without side effects on the Borrowed type.
> > +unsafe impl<'b, T: Send + Sync + FenceCtxOps + 'static> ForeignOwnable for DriverFence<'b, T> {
> > + type Borrowed<'a>
> > + = DriverFenceBorrow<'a, T>
> > + where
> > + Self: 'a;
> > + type BorrowedMut<'a>
> > + = DriverFenceBorrow<'a, T>
>
> We should have a separate type for mutable borrows, IMHO.
No hard objections. But because it's convention, or because you see
other advantages?
Thanks
P.
>
On Wed, 2026-07-15 at 23:00 +0300, Onur Özkan wrote:
> On Fri, 03 Jul 2026 09:31:40 +0200
> Philipp Stanner <phasta(a)kernel.org> wrote:
>
> > +}
> > +
> > +#[allow(unused_unsafe)]
>
> Why is this needed?
Relic from copy pasting around and sorting. Will remove.
P.
>
> > +impl<'a, T: Send + Sync + FenceCtxOps> FenceCtx<T> {
> > + // This can later be extended as a vtable in case other parties need support
> > + // for the more "exotic" callbacks.
Several drivers call dma_buf_fd() — which internally calls fd_install()
— before copy_to_user() returns the fd number to userspace. If
copy_to_user() fails, the fd is already published in the caller's fd
table but the ioctl returns an error, so userspace never learns the fd
number. Worse, the window between fd_install() and copy_to_user()
allows other threads to observe and manipulate the fd (dup, close,
SCM_RIGHTS), making any "close it on the failure path" fix unsafe.
The fix is to split the allocation into three steps: reserve an fd with
get_unused_fd_flags() (not yet visible to other threads), do
copy_to_user(), and only then publish the fd with fd_install() via the
new dma_buf_fd_install() helper. On copy_to_user() failure,
put_unused_fd() + dma_buf_put() cleanly unwind with no user-visible
side effects.
Patch 1 introduces dma_buf_fd_install() in dma-buf.c (wrapping
fd_install() together with the DMA_BUF_TRACE call to preserve export
tracing) and applies the fix to dma-heap.
Patch 2 applies the same fix to fastrpc, which even had a comment
acknowledging the problem could not be fixed before.
v1: https://lore.kernel.org/dri-devel/20260703080922.1838362-1-shoubaineng@gmai…
v2: https://lore.kernel.org/dri-devel/20260710105430.3059661-1-shoubaineng@gmai…
Changes in v3:
- Split into two patches (dma-heap + fastrpc separately)
- Add dma_buf_fd_install() to preserve trace_dma_buf_fd tracepoint
(spotted by T.J. Mercier and sashiko-bot on v2)
- Add fastrpc fix using the new helper (suggested by T.J. Mercier)
Baineng Shou (2):
dma-buf: dma-heap: don't publish fd before copy_to_user() succeeds
misc: fastrpc: don't publish fd before copy_to_user() succeeds
drivers/dma-buf/dma-buf.c | 20 ++++++++++
drivers/dma-buf/dma-heap.c | 80 +++++++++++++++++++-------------------
drivers/misc/fastrpc.c | 16 +++-----
include/linux/dma-buf.h | 1 +
4 files changed, 67 insertions(+), 50 deletions(-)
--
2.34.1
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. These processes then mmap() the buffers and their
access to the device is isolated to the exported ranges. This is an
improvement on sharing the VFIO device fd to subordinate processes,
which would allow unfettered access.
This is achieved by enabling mmap() of vfio-pci DMABUFs, passed by fd
to subordinate processes. Second, a new revocation mechanism is added
to allow the primary process to forcibly revoke access to
previously-shared BAR spans, even if the subordinate processes haven't
cleanly exited.
(The related topic of safe delegation of iommufd control to the
subordinate processes is not addressed here, and is follow-up work.)
The background/rationale is covered in more detail in the RFC cover
letters.
Feedback from the RFCs requested that, instead of creating
DMABUF-specific vm_ops and .fault paths, to go the whole way and
migrate the existing VFIO PCI BAR mmap() to be backed by a DMABUF too,
resulting in a common vm_ops and fault handler for mmap()s of both 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.
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.
Notes on patches
================
PCI/P2PDMA: Split pool-related cleanup out of pci_p2pdma_release()
PCI/P2PDMA: Add CONFIG_PCI_P2PDMA_CORE
Later in the series, vfio-pci's mmap() is going to depend on
pcim_p2pdma_provider() which depended on CONFIG_PCI_P2PDMA, which
in turn depended on ZONE_DEVICE. That isn't available on 32-bit
and some archs, because they lack MEMORY_HOTPLUG and friends.
VFIO does _not_ require actual P2P to be present for basic mmap()
functionality, only for the optional CONFIG_DMA_SHARED_BUFFER
feature.
These split out p2pdma_core.c under CONFIG_PCI_P2PDMA_CORE (which
currently contains pcim_p2pdma_provider()), and an optional
CONFIG_PCI_P2PDMA which depends on ZONE_DEVICE etc. providing
P2P functionality in the existing p2pdma.c. The first splits
out pool cleanup from the release path, and the second does the
refactor/code move to the new file.
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
The first adds a DMABUF VMA fault handler helper to determine
arbitrary-sized PFNs from ranges in DMABUF. The second 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.
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.
vfio/pci: Provide a user-facing name for BAR mappings
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 mapped.
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 vdev->memory_lock is touched; this holds the device
registration so that even if the buffer has been cleaned up, vdev
hasn't been freed and so the lock can be safely taken.
vfio/pci: Permanently revoke a DMABUF on request
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 for use by ..._move() and this new feature.
NOTE: See changelog, by request v4 added a condition to the
existing code to elide the unnecessary invalidation/sync on the
un-revoke path.)
NOTE: Previous versions contained an additional feature patch,
"vfio/pci: Add mmap() attributes to DMABUF feature". This has been
dropped in v5 because:
- The mechanism simply set vma->vm_page_prot. This would be
sufficient for arm64 and other architectures.
- However, (locally-run claude-opus-4-8) Sashiko flagged that, on
x86, additional memtype handling is required to set up the PAT.
Without this, the memtype is returned back to UC- by
pfnmap_setup_cachemode() upon PTE creation.
Most other sources of userspace WC mappings create PTEs eagerly with
e.g. io_remap_pfn_range() which memtype_reserve() WC for the range.
Getting them with lazy-fault used by vfio-pci is more complicated
(e.g. perhaps registering WC for BARs with PAT/MTRRs, and deciding how
to deal with aliasing...). Since this feature is not critical for
this series to be useful, I've decided for now to drop it in favour of
a simpler series now and revisiting this separ*ately.
Testing
=======
(The [RFC ONLY] userspace test program, for QEMU edu-plus, can be
found in the GitHub branch below. It at least illustrates how the
export, map, revoke, and close semantics interoperate.)
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.
Dear Reviewers,
===============
I was grateful for the reviews and Reviewed-Bys on previous versions.
Thanks; I've added some Reviewed-Bys/Acks. I have NOT included your
tags where the patch has materially changed after your review (or
where requested changes ended up more than super-trivial). I hope
that's okay.
End
===
This is based on v7.2-rc3.
These commits are on GitHub for easier browsing, along with
"[RFC ONLY] selftests: vfio: Add standalone vfio_dmabuf_mmap_test":
https://github.com/metamev/linux/compare/v7.2-rc3...dev/mev/vfio-dmabuf-mma…
Thanks for reading,
Matt
================================================================================
Changelog:
v5:
- Rebased on 7.2-rc3
- Dropped the memattr/WC feature (see explanation above).
- "vfio/pci: Convert BAR mmap() to use a DMABUF": Fixed a
potentially-nasty bug (which (locally-run) Sashiko found!) whereby
the unmap_mapping_range() performed in cleanup was passed a range
up from offset zero for the DMABUF size. Initially this was how
all DMABUFs were created and an appropriate zap, but a new version
kept the VFIO region index encoded in the offset -- for BAR > 0 the
unmap span would then mismatch. Instead, pass size 0 to mean an
"all" range. Because the goal is to shoot down everything relating
to one DMABUF and the address_space can only contain things
relating to that DMABUF, this is equivalent and has the bonus of
never failing to match mappings...
Praan, Kevin, I kept your R-Bs on this fix.
- The revoke patch converts vfio_pci_dma_buf_cleanup()'s priv->vdev =
NULL to a WRITE_ONCE, corresponding to the revoke function's
READ_ONCE (performed to test that the VFIO and DMABUF are related).
- Clarified the VFIO_DEVICE_FEATURE_DMA_BUF_REVOKE UAPI comments,
documenting previously-missing error cases and their reasons.
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):
PCI/P2PDMA: Split pool-related cleanup out of pci_p2pdma_release()
PCI/P2PDMA: Add CONFIG_PCI_P2PDMA_CORE
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: Provide a user-facing name for BAR mappings
vfio/pci: Clean up BAR zap and revocation
vfio/pci: Support mmap() of a VFIO DMABUF
vfio/pci: Permanently revoke a DMABUF on request
MAINTAINERS | 2 +-
drivers/pci/Kconfig | 5 +
drivers/pci/Makefile | 1 +
drivers/pci/p2pdma.c | 113 +---
drivers/pci/p2pdma.h | 29 +
drivers/pci/p2pdma_core.c | 122 +++++
drivers/vfio/pci/Kconfig | 5 +-
drivers/vfio/pci/Makefile | 3 +-
.../vfio/pci/hisilicon/hisi_acc_vfio_pci.c | 8 +
drivers/vfio/pci/vfio_pci_config.c | 30 +-
drivers/vfio/pci/vfio_pci_core.c | 210 +++++--
drivers/vfio/pci/vfio_pci_dmabuf.c | 515 +++++++++++++++---
drivers/vfio/pci/vfio_pci_priv.h | 53 +-
include/linux/pci-p2pdma.h | 24 +-
include/linux/pci.h | 2 +-
include/linux/vfio_pci_core.h | 1 +
include/uapi/linux/vfio.h | 25 +
17 files changed, 875 insertions(+), 273 deletions(-)
create mode 100644 drivers/pci/p2pdma.h
create mode 100644 drivers/pci/p2pdma_core.c
--
2.50.1 (Apple Git-155)
Slope features a very distinct neon visual style. The bright colors contrast against the dark background perfectly. This makes the path clear even when you are moving at high speeds. The aesthetic is clean and modern. It avoids unnecessary clutter that might distract you during the game. This focus on visuals helps you stay locked into the core gameplay loop.
The environment feels empty yet threatening. The void below the track creates a sense of danger. You are always one wrong tilt away from falling. This creates a high-stakes atmosphere that keeps you engaged. The simplicity of the graphics is a strength. It allows the game to run smoothly on almost any device without any lag or performance issues at all.
https://slope-play.com
You might find the visuals hypnotic after a while. The glowing lines and moving platforms can create a flow state. This is when the game becomes truly special. You move by instinct rather than conscious thought. You react before you even see the obstacle clearly. This level of immersion is why so many players spend hours trying to beat their records.
Heardle has quickly become one of the most talked-about music puzzle games online. Designed for players of all skill levels, heardle invites you to guess songs from short audio clips while enjoying a relaxed yet competitive experience. https://heardleonline.io/
Gameplay Overview
The mechanics are straightforward but clever. You begin with a brief audio clip—usually just one second long. If you can’t identify the song, you can skip or guess incorrectly to unlock longer snippets. You have a maximum of six attempts to get it right.
A Unique Twist on Wordle
Unlike Wordle’s text-based gameplay, Heardle focuses entirely on sound. There are no color-coded hints or letter placements—only your listening skills. This makes it both simpler and more immersive.
Explore Variants and Modes
One of Heardle’s strengths is its variety. Players can explore:
Decade-based editions (80s, 90s, 2000s, etc.)
Genre-focused versions like rock, pop, or K-pop
Unlimited modes for extended gameplay
Why You Should Play Heardle
Heardle isn’t just a game—it’s an experience. It challenges your memory, sharpens your listening skills, and introduces you to new music. Whether you’re playing solo or sharing results with friends, it’s a great way to connect through music.
If you’re searching for a fun, engaging, and easy-to-learn music guessing game, Heardle is the perfect choice. Give it a try and see how many songs you can recognize.
https://holeonline.io
If you're looking for a game that's simple, easy to play, yet still offers a thrilling competitive experience, then Hole IO is definitely a must-try. The most appealing aspect of the game is that each match lasts only 2 minutes, forcing players to utilize every second to grow their black hole as quickly as possible. At the start, you're just a tiny hole, only able to swallow small objects like lampposts, signs, or bushes. However, the more objects you swallow, the larger your hole becomes, opening up the possibility of "eating" cars, houses, skyscrapers, and even other opponents on the map. This continuous growth mechanism creates an extremely satisfying feeling and makes players want to try another match to achieve a higher score. Within that short 120-second timeframe, you must plan your moves strategically, prioritizing areas with many small objects to increase your size quickly before moving on to larger targets. At the same time, you also need to pay attention to your opponents' positions because if they are bigger, you can become "meal" at any time. Conversely, when you are strong enough, hunting down and devouring other players will help you significantly increase your score and climb to the top of the leaderboard. The fast pace, intuitive gameplay, and unexpected twists make each Hole IO match a different experience. Just one right decision in the last few seconds can completely overtake all your opponents to win the championship. With colorful graphics, simple controls, and high entertainment value, Hole IO is suitable for all ages, from those who just want to have a few minutes of fun to gamers who like to compete for high scores. So, if you believe in your reflexes, strategy, and speed, step into the Hole IO arena and prove that in just 2 minutes, you can still become a champion.
https://snowrideronline.io
Snow Rider 3D is an engaging and entertaining game where players control a snowmobile traversing snow-covered paths. The gameplay is simple but requires quick reflexes to dodge trees, rocks, snowmen, and many other obstacles that appear constantly. The increasing speed makes each level more dramatic, providing a thrilling and challenging experience for players.
Not only does it boast beautiful 3D graphics with vibrant winter scenery, Snow Rider 3D also offers an enjoyable entertainment experience for all ages. Players can collect rewards to unlock unique snowmobile models, adding motivation to conquer longer distances. With easy-to-learn controls but challenging high scores, the game is a great choice for training reflexes, concentration, and enjoying relaxing moments after school or work.
<a href="https://snowrideronline.io">Snow Rider 3D</a> is an engaging and entertaining game where players control a snowmobile traversing snow-covered paths. The gameplay is simple but requires quick reflexes to dodge trees, rocks, snowmen, and many other obstacles that appear constantly. The increasing speed makes each level more dramatic, providing a thrilling and challenging experience for players.
Not only does it boast beautiful 3D graphics with vibrant winter scenery, Snow Rider 3D also offers an enjoyable entertainment experience for all ages. Players can collect rewards to unlock unique snowmobile models, adding motivation to conquer longer distances. With easy-to-learn controls but challenging high scores, the game is a great choice for training reflexes, concentration, and enjoying relaxing moments after school or work.
The patch set allows to register a dmabuf to an io_uring instance for
a specified file and use it with io_uring read / write requests. The
infrastructure is not tied to io_uring and there could be more users
in the future. A similar idea was attempted some years ago by Keith [1],
from where I borrowed a good number of changes, and later was brough up
by Tushar and Vishal from Intel.
It's an opt-in feature for files, and they need to implement a new
file operation to use it. Only NVMe block devices are supported in this
series. The user API is built on top of io_uring's "registered buffers",
where a dmabuf is registered in a special way, but after it can be used
as any other "registered buffer" with IORING_OP_{READ,WRITE}_FIXED
requests. It's created via a new file operation and the resulted map is
then passed through the I/O stack in a new iterator type. There is some
additional infrastructure to bind it all, which also counts requests
using a dmabuf map and managing lifetimes, which is used to implement
map invalidation.
It was tested for GPU <-> NVMe transfers. Also, as it maintains a
long-term dma mapping, it helps with the IOMMU cost. The numbers
below are for udmabuf reads previously run by Anuj for different
IOMMU modes:
- STRICT: before = 570 KIOPS, after = 5.01 MIOPS
- LAZY: before = 1.93 MIOPS, after = 5.01 MIOPS
- PASSTHROUGH: before = 5.01 MIOPS, after = 5.01 MIOPS
There are some liburing tests that can serve as an example:
git: https://github.com/isilence/liburing.git rw-dmabuf-tests-v3
url: https://github.com/isilence/liburing/tree/rw-dmabuf-tests-v3
[1] https://lore.kernel.org/io-uring/20220805162444.3985535-1-kbusch@fb.com/
v3: - Rework io_uring registration
- Move token/map infrastructure code out of blk-mq
- Simplify callbacks: remove a separate blk-mq table, which was
mostly just forwarding calls (to nvme).
- Don't skip dma sync depending on request direction
- Fix a couple of hangs
- Rename s/dma/dmabuf/
- Other small changes
v2: - Don't pass raw dma addresses, wrap it into a driver specific object
- Split into two objects: token and map
- Implement move_notify
Pavel Begunkov (10):
file: add callback for creating long-term dmabuf maps
iov_iter: add iterator type for dmabuf maps
block: move bvec init into __bio_clone
block: introduce dma map backed bio type
lib: add dmabuf token infrastructure
block: forward create_dmabuf_token to drivers
nvme-pci: implement dma_token backed requests
io_uring/rsrc: introduce buf registration structure
io_uring/rsrc: extend buffer update
io_uring/rsrc: add dmabuf backed registered buffers
block/bio.c | 28 +++-
block/blk-merge.c | 14 ++
block/blk.h | 3 +-
block/fops.c | 16 ++
drivers/nvme/host/pci.c | 282 ++++++++++++++++++++++++++++++++
include/linux/bio.h | 19 ++-
include/linux/blk-mq.h | 9 +
include/linux/blk_types.h | 8 +-
include/linux/fs.h | 2 +
include/linux/io_dmabuf_token.h | 92 +++++++++++
include/linux/io_uring_types.h | 5 +
include/linux/uio.h | 11 ++
include/uapi/linux/io_uring.h | 31 +++-
io_uring/io_uring.c | 3 +-
io_uring/rsrc.c | 266 +++++++++++++++++++++++++-----
io_uring/rsrc.h | 30 +++-
io_uring/rw.c | 4 +-
lib/Kconfig | 4 +
lib/Makefile | 2 +
lib/io_dmabuf_token.c | 272 ++++++++++++++++++++++++++++++
lib/iov_iter.c | 29 +++-
21 files changed, 1071 insertions(+), 59 deletions(-)
create mode 100644 include/linux/io_dmabuf_token.h
create mode 100644 lib/io_dmabuf_token.c
--
2.53.0