* [PATCH 1/2] rust: dma_buf: add stub dma_fence abstraction
2026-05-05 13:29 [PATCH 0/2] Rust support for drm_gpuvm_exec Alice Ryhl
@ 2026-05-05 13:29 ` Alice Ryhl
2026-05-05 13:29 ` [PATCH 2/2] drm/gpuvm: rust: add drm_gpuvm_exec support Alice Ryhl
1 sibling, 0 replies; 3+ messages in thread
From: Alice Ryhl @ 2026-05-05 13:29 UTC (permalink / raw)
To: Danilo Krummrich, Matthew Brost, Thomas Hellström,
Daniel Almeida, Boris Brezillon, Gary Guo, Onur Özkan,
Philipp Stanner
Cc: Sumit Semwal, Christian König, Miguel Ojeda, Boqun Feng,
Björn Roy Baron, Benno Lossin, Andreas Hindborg,
Trevor Gross, linux-kernel, rust-for-linux, dri-devel, Alice Ryhl
From: Philipp Stanner <pstanner@redhat.com>
This adds a trivial DMA Fence type for use in other abstractions that
need to take a DMA fence as a parameter. For now, the type is a stub,
but may be used with fences defined by C.
Signed-off-by: Philipp Stanner <pstanner@redhat.com>
Signed-off-by: Alice Ryhl <aliceryhl@google.com>
---
This stub is included only for completeness. Most likely we will land
this on top of the Philipp's patch that actually adds Fence for real,
and this stub commit will not be necessary.
Taken from:
https://gitlab.freedesktop.org/pstanner/linux-drm-work/-/merge_requests/1
---
rust/kernel/dma_buf/dma_fence.rs | 32 ++++++++++++++++++++++++++++++++
rust/kernel/dma_buf/mod.rs | 7 +++++++
rust/kernel/lib.rs | 1 +
3 files changed, 40 insertions(+)
diff --git a/rust/kernel/dma_buf/dma_fence.rs b/rust/kernel/dma_buf/dma_fence.rs
new file mode 100644
index 000000000000..135df74013db
--- /dev/null
+++ b/rust/kernel/dma_buf/dma_fence.rs
@@ -0,0 +1,32 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (C) 2025, 2026 Red Hat Inc.:
+// - Philipp Stanner <pstanner@redhat.com>
+
+//! DMA Fence support.
+//!
+//! Reference: <https://docs.kernel.org/driver-api/dma-buf.html#c.dma_fence>
+//!
+//! C header: [`include/linux/dma-fence.h`](srctree/include/linux/dma-fence.h)
+
+use crate::{
+ bindings,
+ prelude::*,
+ types::Opaque, //
+};
+
+/// A dma fence.
+#[pin_data]
+#[repr(transparent)]
+pub struct Fence {
+ #[pin]
+ inner: Opaque<bindings::dma_fence>,
+}
+
+impl Fence {
+ /// Access the raw dma fence.
+ #[inline]
+ pub fn as_raw(&self) -> *mut bindings::dma_fence {
+ self.inner.get()
+ }
+}
diff --git a/rust/kernel/dma_buf/mod.rs b/rust/kernel/dma_buf/mod.rs
new file mode 100644
index 000000000000..b66e747c35ad
--- /dev/null
+++ b/rust/kernel/dma_buf/mod.rs
@@ -0,0 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0 OR MIT
+
+//! DMA-buf subsystem abstractions.
+
+pub mod dma_fence;
+
+pub use self::dma_fence::Fence;
diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs
index b72b2fbe046d..a05ccaa7598c 100644
--- a/rust/kernel/lib.rs
+++ b/rust/kernel/lib.rs
@@ -63,6 +63,7 @@
pub mod device_id;
pub mod devres;
pub mod dma;
+pub mod dma_buf;
pub mod driver;
#[cfg(CONFIG_DRM = "y")]
pub mod drm;
--
2.54.0.545.g6539524ca2-goog
^ permalink raw reply related [flat|nested] 3+ messages in thread* [PATCH 2/2] drm/gpuvm: rust: add drm_gpuvm_exec support
2026-05-05 13:29 [PATCH 0/2] Rust support for drm_gpuvm_exec Alice Ryhl
2026-05-05 13:29 ` [PATCH 1/2] rust: dma_buf: add stub dma_fence abstraction Alice Ryhl
@ 2026-05-05 13:29 ` Alice Ryhl
1 sibling, 0 replies; 3+ messages in thread
From: Alice Ryhl @ 2026-05-05 13:29 UTC (permalink / raw)
To: Danilo Krummrich, Matthew Brost, Thomas Hellström,
Daniel Almeida, Boris Brezillon, Gary Guo, Onur Özkan,
Philipp Stanner
Cc: Sumit Semwal, Christian König, Miguel Ojeda, Boqun Feng,
Björn Roy Baron, Benno Lossin, Andreas Hindborg,
Trevor Gross, linux-kernel, rust-for-linux, dri-devel, Alice Ryhl
This adds support for simple usage of drm_gpuvm_exec() for locking all
of the dma reservations and adding fences to them. For more complex
usage that does not involve locking all reservations, it is expected
that the ww-mutex abstractions will be used instead.
Signed-off-by: Alice Ryhl <aliceryhl@google.com>
---
rust/bindings/bindings_helper.h | 2 ++
rust/helpers/drm_gpuvm.c | 6 ++++
rust/kernel/dma_buf/mod.rs | 17 ++++++++++
rust/kernel/drm/gpuvm/mod.rs | 71 +++++++++++++++++++++++++++++++++++++++++
4 files changed, 96 insertions(+)
diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helper.h
index 1124785e210b..3978682a6f2e 100644
--- a/rust/bindings/bindings_helper.h
+++ b/rust/bindings/bindings_helper.h
@@ -151,6 +151,8 @@ const vm_flags_t RUST_CONST_HELPER_VM_MIXEDMAP = VM_MIXEDMAP;
const vm_flags_t RUST_CONST_HELPER_VM_HUGEPAGE = VM_HUGEPAGE;
const vm_flags_t RUST_CONST_HELPER_VM_NOHUGEPAGE = VM_NOHUGEPAGE;
+const u32 RUST_CONST_HELPER_DRM_EXEC_INTERRUPTIBLE_WAIT = DRM_EXEC_INTERRUPTIBLE_WAIT;
+
#if IS_ENABLED(CONFIG_GPU_BUDDY)
const unsigned long RUST_CONST_HELPER_GPU_BUDDY_RANGE_ALLOCATION = GPU_BUDDY_RANGE_ALLOCATION;
const unsigned long RUST_CONST_HELPER_GPU_BUDDY_TOPDOWN_ALLOCATION = GPU_BUDDY_TOPDOWN_ALLOCATION;
diff --git a/rust/helpers/drm_gpuvm.c b/rust/helpers/drm_gpuvm.c
index 4130b6325213..30fb1777fbf2 100644
--- a/rust/helpers/drm_gpuvm.c
+++ b/rust/helpers/drm_gpuvm.c
@@ -23,4 +23,10 @@ bool rust_helper_drm_gpuvm_is_extobj(struct drm_gpuvm *gpuvm,
return drm_gpuvm_is_extobj(gpuvm, obj);
}
+__rust_helper
+void rust_helper_drm_gpuvm_exec_unlock(struct drm_gpuvm_exec *vm_exec)
+{
+ drm_gpuvm_exec_unlock(vm_exec);
+}
+
#endif // CONFIG_RUST_DRM_GPUVM
diff --git a/rust/kernel/dma_buf/mod.rs b/rust/kernel/dma_buf/mod.rs
index b66e747c35ad..234936ba8265 100644
--- a/rust/kernel/dma_buf/mod.rs
+++ b/rust/kernel/dma_buf/mod.rs
@@ -5,3 +5,20 @@
pub mod dma_fence;
pub use self::dma_fence::Fence;
+
+/// How the fences from a `dma_resv` obj are used.
+///
+/// Please see [the C-side documentation][dma_resv_usage] for more details.
+///
+/// [dma_resv_usage]: https://docs.kernel.org/driver-api/dma-buf.html#c.dma_resv_usage
+#[repr(u32)]
+pub enum DmaResvUsage {
+ /// For in kernel memory management only (e.g. copying, clearing memory).
+ Kernel = bindings::dma_resv_usage_DMA_RESV_USAGE_KERNEL,
+ /// Implicit write synchronization for userspace submissions.
+ Write = bindings::dma_resv_usage_DMA_RESV_USAGE_WRITE,
+ /// Implicit read synchronization for userspace submissions.
+ Read = bindings::dma_resv_usage_DMA_RESV_USAGE_READ,
+ /// No implicit sync (e.g. preemption fences, page table updates, TLB flushes).
+ Bookkeep = bindings::dma_resv_usage_DMA_RESV_USAGE_BOOKKEEP,
+}
diff --git a/rust/kernel/drm/gpuvm/mod.rs b/rust/kernel/drm/gpuvm/mod.rs
index ae58f6f667c1..a52fb25f22ff 100644
--- a/rust/kernel/drm/gpuvm/mod.rs
+++ b/rust/kernel/drm/gpuvm/mod.rs
@@ -16,6 +16,7 @@
Flags as AllocFlags, //
},
bindings,
+ dma_buf::{DmaResvUsage, Fence},
drm,
drm::gem::IntoGEMObject,
error::to_result,
@@ -216,6 +217,30 @@ pub fn obtain(
Ok(GpuVmBoAlloc::new(self, obj, data)?.obtain())
}
+ /// Prepare this GPUVM.
+ ///
+ /// The parameter indicates how many fences to preallocate space for.
+ #[inline]
+ pub fn prepare(&self, num_fences: u32) -> impl PinInit<GpuVmExec<'_, T>, Error> {
+ try_pin_init!(GpuVmExec {
+ exec <- Opaque::try_ffi_init(|exec: *mut bindings::drm_gpuvm_exec| {
+ // SAFETY: exec is valid but unused memory, so we can write.
+ unsafe {
+ ptr::write_bytes(exec, 0u8, 1usize);
+ ptr::write(&raw mut (*exec).vm, self.as_raw());
+ ptr::write(&raw mut (*exec).flags, bindings::DRM_EXEC_INTERRUPTIBLE_WAIT);
+ ptr::write(&raw mut (*exec).num_fences, num_fences);
+ }
+
+ // SAFETY: If successful, this `struct drm_gpuvm_exec` remains valid until this is
+ // unlocked because it's pinned and unlocks it in drop. The contained pointer to
+ // `self` remains valid because `GpuVmExec` borrows from `self`.
+ to_result(unsafe { bindings::drm_gpuvm_exec_lock(exec) })
+ }),
+ _gpuvm: PhantomData,
+ })
+ }
+
/// Clean up buffer objects that are no longer used.
#[inline]
pub fn deferred_cleanup(&self) {
@@ -326,3 +351,49 @@ fn deref(&self) -> &GpuVm<T> {
&self.0
}
}
+
+/// The exec token for preparing the objects.
+///
+/// # Invariants
+///
+/// Owns a GPUVM exec context.
+#[pin_data(PinnedDrop)]
+pub struct GpuVmExec<'vm, T: DriverGpuVm> {
+ #[pin]
+ exec: Opaque<bindings::drm_gpuvm_exec>,
+ _gpuvm: PhantomData<&'vm mut GpuVm<T>>,
+}
+
+impl<'vm, T: DriverGpuVm> GpuVmExec<'vm, T> {
+ /// Add a fence.
+ ///
+ /// The caller must ensure that the preallocated space for fences is sufficient.
+ #[inline]
+ pub fn resv_add_fence(
+ &self,
+ fence: &Fence,
+ private_usage: DmaResvUsage,
+ extobj_usage: DmaResvUsage,
+ ) {
+ // SAFETY: This method takes a refcount on the fence, so it's only required to be valid for
+ // the duration of this method. If there is not enough space for the pre-allocated fence,
+ // then this leads to a BUG_ON() but does not trigger UB.
+ unsafe {
+ bindings::drm_gpuvm_resv_add_fence(
+ (*self.exec.get()).vm,
+ &raw mut (*self.exec.get()).exec,
+ fence.as_raw(),
+ private_usage as u32,
+ extobj_usage as u32,
+ )
+ }
+ }
+}
+
+#[pinned_drop]
+impl<'vm, T: DriverGpuVm> PinnedDrop for GpuVmExec<'vm, T> {
+ fn drop(self: Pin<&mut Self>) {
+ // SAFETY: We hold the lock, so it's safe to unlock.
+ unsafe { bindings::drm_gpuvm_exec_unlock(self.exec.get()) };
+ }
+}
--
2.54.0.545.g6539524ca2-goog
^ permalink raw reply related [flat|nested] 3+ messages in thread