kernel/dma_buf/dma_fence.rs
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (C) 2025-2026 Red Hat Inc.
4 * Author: Philipp Stanner <pstanner@redhat.com>
5 */
6
7//! DMA Fence support.
8//!
9//! Reference: <https://docs.kernel.org/driver-api/dma-buf.html#c.dma_fence>
10//!
11//! header: [`include/linux/dma-fence.h`](srctree/include/linux/dma-fence.h)
12
13use crate::{
14 alloc::AllocError,
15 bindings,
16 container_of,
17 error::to_result,
18 prelude::*,
19 types::ForeignOwnable,
20 types::Opaque, //
21};
22
23use core::{
24 marker::PhantomData,
25 mem::ManuallyDrop,
26 ops::Deref,
27 ptr,
28 ptr::{
29 drop_in_place,
30 NonNull, //
31 }, //
32};
33
34use kernel::{
35 str::CString,
36 sync::{
37 aref::{
38 ARef,
39 AlwaysRefCounted, //
40 },
41 atomic::{
42 Atomic,
43 Relaxed, //
44 },
45 rcu::rcu_barrier, //
46 }, //
47};
48
49/// VTable for dma_fence backend_ops callbacks.
50//
51// Mandatory dma_fence backend_ops are implemented implicitly through
52// [`FenceContext`]. Additional ones shall get implemented on this trait.
53pub trait FenceContextOps {
54 /// The generic payload data for [`DriverFence`]s created on this fctx.
55 type FenceDataType: Send + Sync;
56}
57
58/// A dma-fence context. A fence context takes care of associating related fences
59/// with each other, providing each with raising sequence numbers and a common
60/// identifier.
61#[pin_data(PinnedDrop)]
62pub struct FenceContext<T: FenceContextOps + Send + Sync> {
63 /// The fence context number.
64 nr: u64,
65 /// The sequence number for the next fence created.
66 seqno: Atomic<u64>,
67 // The name parameters can be accessed by the dma_fence backend_ops. UAF
68 // errors are prevented by the `call_rcu()` in `drop_driver_fence_data()`.
69 /// The name of the driver this FenceContext's fences belong to.
70 driver_name: CString,
71 /// The name of the timeline this FenceContext's fences belong to.
72 timeline_name: CString,
73 /// The number of all unsignaled fences on this context.
74 // Used to prevent bugs due to forgotten fences.
75 //
76 // The lifetime on `DriverFence`s should typically prevent this from
77 // happening.
78 //
79 // However, we cannot fully guarantee in Rust that `DriverFence`s will not
80 // be forgotten, e.g., through `core::mem::forget()`. This could circumvent
81 // the lifetime which intends to enforce that all fences disappear before
82 // their context.
83 nr_of_unsignaled_fences: Atomic<usize>,
84 /// The user's data.
85 #[pin]
86 data: T,
87}
88
89impl<'a, T: Send + Sync + FenceContextOps> FenceContext<T> {
90 // This can later be extended as a vtable in case other parties need support
91 // for the more "exotic" callbacks.
92 const OPS: bindings::dma_fence_ops = bindings::dma_fence_ops {
93 get_driver_name: Some(Self::get_driver_name),
94 get_timeline_name: Some(Self::get_timeline_name),
95 enable_signaling: None,
96 signaled: None,
97 // Deprecated.
98 wait: None,
99 // Must never be implemented for these abstractions.
100 release: None,
101 set_deadline: None,
102 };
103
104 /// Create a new `FenceContext`.
105 pub fn new<E>(
106 initial_seqno: u64,
107 driver_name: &CStr,
108 timeline_name: &CStr,
109 data: impl PinInit<T, E>,
110 ) -> impl PinInit<Self, Error>
111 where
112 Error: From<E>,
113 {
114 let driver_name = CString::try_from(driver_name);
115 let timeline_name = CString::try_from(timeline_name);
116 try_pin_init!(Self {
117 // SAFETY: `dma_fence_context_alloc()` merely works on a global
118 // atomic. Parameter `1` is the number of contexts we want to
119 // allocate.
120 nr: unsafe { bindings::dma_fence_context_alloc(1) },
121 seqno: Atomic::new(initial_seqno),
122 driver_name: driver_name?,
123 timeline_name: timeline_name?,
124 nr_of_unsignaled_fences: Atomic::new(0),
125 data <- data,
126 })
127 }
128
129 fn next_seqno(&self) -> u64 {
130 self.seqno.fetch_add(1, Relaxed)
131 }
132
133 /// Allocate the memory for a [`DriverFence`] and already store `data` inside.
134 ///
135 /// This is needed because many times, creation of a [`DriverFence`] must not
136 /// fail, and allocating might deadlock in some situations.
137 ///
138 /// The `data` you pass here must not perform any operations that are illegal
139 /// in atomic context in its [`Drop`] implementation.
140 pub fn new_fence_allocation(
141 &self,
142 data: T::FenceDataType,
143 ) -> Result<DriverFenceAllocation<'_, T>> {
144 let fence_data = DriverFenceData {
145 rcu_head: Default::default(),
146 // `inner` remains uninitialized until a `DriverFence` takes over.
147 inner: Fence {
148 inner: Opaque::uninit(),
149 },
150 fctx: self,
151 data,
152 };
153
154 // In order to support the C dma_fence callbacks, it is necessary for
155 // a `Fence` and a `DriverFence` to live in the same allocation,
156 // because the C backend passes a dma_fence, from which the driver most
157 // likely wants to be able to access its `data` in `DriverFence`.
158 //
159 // Hence, we need the manage the memory manually. It will be freed by the
160 // C backend automatically once the refcount within `Fence` drops to 0.
161 let data = KBox::new(fence_data, GFP_KERNEL | __GFP_ZERO)?;
162
163 Ok(DriverFenceAllocation {
164 data,
165 ops: &Self::OPS,
166 })
167 }
168
169 extern "C" fn get_driver_name(ptr: *mut bindings::dma_fence) -> *const c_char {
170 // SAFETY: The C backend only invokes this callback with `ptr` pointing
171 // to a valid, unsignaled `bindings::dma_fence`. All fences created in
172 // this module always reside within `Fence` which always resides in a
173 // `DriverFenceData`, thus satisfying the function's safety
174 // requirements.
175 let fctx = unsafe { Self::from_raw_fence(ptr) };
176
177 fctx.driver_name.as_char_ptr()
178 }
179
180 extern "C" fn get_timeline_name(ptr: *mut bindings::dma_fence) -> *const c_char {
181 // SAFETY: The C backend only invokes this callback with `ptr` pointing
182 // to a valid, unsignaled `bindings::dma_fence`. All fences created in
183 // this module always reside within `Fence` which always resides in a
184 // `DriverFenceData`, thus satisfying the function's safety
185 // requirements.
186 let fctx = unsafe { Self::from_raw_fence(ptr) };
187
188 fctx.timeline_name.as_char_ptr()
189 }
190
191 /// Create a [`FenceContext`] from an associated [`bindings::dma_fence`].
192 ///
193 /// # Safety
194 ///
195 /// `ptr` must be a valid pointer to a [`bindings::dma_fence`] which resides
196 /// within a [`Fence`], which in turn resides in a [`DriverFenceData`].
197 unsafe fn from_raw_fence(ptr: *mut bindings::dma_fence) -> &'a Self {
198 let opaque_fence = Opaque::cast_from(ptr);
199
200 // SAFETY: Safe due to the function's overall safety requirements.
201 let fence_ptr = unsafe { container_of!(opaque_fence, Fence, inner) };
202
203 // CAST: `DriverFenceData` is `repr(C)` and a `Fence` is its first member.
204 let fence_data_ptr: *const DriverFenceData<'a, T> = fence_ptr.cast();
205
206 // SAFETY: Safe because of the comments directly above.
207 let fence_data = unsafe { &*fence_data_ptr };
208
209 fence_data.fctx
210 }
211}
212
213#[pinned_drop]
214impl<T: FenceContextOps + Send + Sync> PinnedDrop for FenceContext<T> {
215 fn drop(self: Pin<&mut Self>) {
216 // Fence ops callbacks can be called on unsignaled fences. Since these
217 // callbacks can access the fence context and its data, it needs to be
218 // guaranteed that a context only drops after all associated
219 // `DriverFence`s have been dropped. This is unlikely to occur, but
220 // would result in silent UAF. Throw a panic to prevent that.
221 //
222 // TODO:
223 // It would be better if the fence context signals all forgotten fences
224 // itself. To do so, it would keep a list of unsignaled fences. That
225 // list's members would have to be pre-allocated (see
226 // `FenceCallback::new_fence_allocation()`).
227 if self.nr_of_unsignaled_fences.load(Relaxed) != 0 {
228 panic!("Forgotten fences in FenceContext.");
229 }
230
231 // Ensure that the driver cannot unload while there are still dma_fence
232 // callbacks running. At the same time, the RCU barrier addresses the
233 // problem inherited by the C backend, in which backend ops callbacks
234 // might be accessing the fence while it is being signaled (or shortly
235 // after). This could cause UAF access on the fence context's
236 // `fctx.driver_name` and `fctx.timeline_name`.
237 //
238 // Wait for the RCU callbacks in `DriverFence::drop`.
239 rcu_barrier();
240 }
241}
242
243/// Error type for fence callback registration.
244///
245/// Generic over `T` so that `AlreadySignaled` can return the callback to the
246/// caller, allowing it to reclaim any resources owned by the callback (e.g.,
247/// a fence handle that needs to be signaled).
248#[derive(Debug)]
249pub enum CallbackError<T> {
250 /// The fence was already signaled. The callback is returned so the caller
251 /// can extract owned resources without losing them.
252 AlreadySignaled(T),
253 /// Some other error occurred during registration.
254 Other(Error),
255}
256
257impl<T> From<CallbackError<T>> for Error {
258 #[inline]
259 fn from(err: CallbackError<T>) -> Self {
260 match err {
261 CallbackError::AlreadySignaled(_) => ENOENT,
262 CallbackError::Other(e) => e,
263 }
264 }
265}
266
267impl<T> From<AllocError> for CallbackError<T> {
268 #[inline]
269 fn from(e: AllocError) -> Self {
270 CallbackError::Other(Error::from(e))
271 }
272}
273
274/// Trait for callbacks that can be registered on fences.
275///
276/// When the fence signals, the callback will be invoked.
277///
278/// # Example
279///
280/// ```rust
281/// use kernel::dma_buf::FenceCallback;
282///
283/// struct MyCallback {
284/// // Your callback state here
285/// }
286///
287/// impl FenceCallback for MyCallback {
288/// fn on_signal(&mut self) {
289/// pr_info!("Fence signaled!\n");
290/// // Handle fence completion
291/// }
292/// }
293/// ```
294pub trait FenceCallback: Send {
295 /// Called when the fence is signaled.
296 ///
297 /// This is called from the fence signaling path, which may be in interrupt
298 /// context or with locks held, which is why `self` is only borrowed, so that
299 /// it cannot drop. Implementations must not sleep or perform
300 /// long-running operations.
301 ///
302 /// An implementation likely wants to inform itself (e.g., through a work item)
303 /// within this callback that the associated [`FenceCallbackRegistration`]
304 /// can now be dropped.
305 fn on_signal(&mut self);
306}
307
308/// A callback registration on a fence.
309///
310/// When this object is dropped, the callback is automatically removed if it
311/// hasn't been called yet.
312#[pin_data(PinnedDrop)]
313pub struct FenceCallbackRegistration<T: FenceCallback> {
314 #[pin]
315 callback_foreign: Opaque<bindings::dma_fence_cb>,
316 callback: ManuallyDrop<T>,
317 fence: ARef<Fence>,
318}
319
320impl<T: FenceCallback> FenceCallbackRegistration<T> {
321 /// Create a [`PinInit`] closure for registering a callback on a fence.
322 ///
323 /// The actual attempt at registering the callback will take place once you
324 /// call an allocator's `pin_init()` function.
325 ///
326 /// On success the callback is pinned in place and will fire when the fence
327 /// signals. On `AlreadySignaled` the callback is returned to the caller so
328 /// that owned resources can be reclaimed.
329 ///
330 /// # Safety
331 ///
332 /// The callback registration must not be forgotten.
333 pub unsafe fn new<'a>(
334 fence: &'a Fence,
335 callback: T,
336 ) -> impl PinInit<Self, CallbackError<T>> + 'a
337 where
338 T: 'a,
339 {
340 try_pin_init!(Self {
341 // We need to fully initialize the fence because after
342 // `dma_fence_add_callback()` ran, the callback might immediately
343 // get invoked.
344 callback: ManuallyDrop::new(callback),
345 fence: ARef::from(fence),
346 callback_foreign <- Opaque::try_ffi_init(|ptr| {
347 // SAFETY: `fence.inner.get()` is a valid, initialized `struct
348 // dma_fence`. `ptr` points to the `struct dma_fence_cb` field
349 // within the pinned allocation, so it remains valid until
350 // `dma_fence_remove_callback()` in `PinnedDrop` or until the
351 // callback fires.
352 let ret = unsafe {
353 to_result(bindings::dma_fence_add_callback(
354 fence.inner.get(),
355 ptr,
356 Some(Self::dma_fence_callback),
357 ))
358 };
359 match ret {
360 Ok(()) => Ok(()),
361 Err(e) => {
362 // SAFETY: We could not register the callback. Thus,
363 // C will not use it. So we can just take it back
364 // and pass it to the user again.
365 let cb_back = unsafe { ManuallyDrop::take(callback) };
366 if e == ENOENT {
367 Err(CallbackError::AlreadySignaled(cb_back))
368 } else {
369 Err(CallbackError::Other(e))
370 }
371 },
372 }
373 }),
374 }? CallbackError<T>)
375 }
376
377 /// Raw dma fence callback that is called by the C code.
378 ///
379 /// # Safety
380 ///
381 /// This is only called by the dma_fence subsystem with valid pointers.
382 unsafe extern "C" fn dma_fence_callback(
383 _fence: *mut bindings::dma_fence,
384 callback_foreign: *mut bindings::dma_fence_cb,
385 ) {
386 let ptr = Opaque::cast_from(callback_foreign).cast_mut();
387
388 // SAFETY: All callbacks we can receive here have been created in such a way that they are
389 // embedded into a `FenceCallbackRegistration`.
390 let reg: *mut Self = unsafe { container_of!(ptr, Self, callback_foreign) };
391
392 // SAFETY: `reg` is a valid `Self` pointer.
393 //
394 // The backend ensures synchronisation so whoever holds the registration object cannot drop
395 // it while this code is running. See `FenceCallbackRegistration::drop`.
396 unsafe { (*reg).callback.on_signal() };
397 }
398
399 /// Returns a reference to the fence this callback is registered on.
400 #[inline]
401 pub fn fence(&self) -> &Fence {
402 &self.fence
403 }
404}
405
406#[pinned_drop]
407impl<T: FenceCallback> PinnedDrop for FenceCallbackRegistration<T> {
408 fn drop(self: Pin<&mut Self>) {
409 // Always call `dma_fence_remove_callback()`, even if the callback
410 // already ran. This is necessary for synchronization:
411 // `dma_fence_remove_callback()` acquires `fence->lock`, which ensures
412 // that any in-flight `dma_fence_signal()` (which calls our callback
413 // while holding the same lock) has completed before we free the struct.
414 //
415 // Without this, Drop can race with a concurrent signal:
416 // CPU0 (signal, lock held): take() -> on_signal(fence_ref) (in progress)
417 // CPU1 (drop): skips lock -> frees struct
418 // CPU0: accesses fence_ref -> use-after-free
419 //
420 // When the callback has already fired, the signal path detached the
421 // list node via `INIT_LIST_HEAD()`, so dma_fence_remove_callback just
422 // sees an empty node and returns false — the lock acquisition is the
423 // only thing that matters.
424 //
425 // SAFETY: The fence pointer is valid and the cb was initialized by
426 // `dma_fence_add_callback()` during construction.
427 unsafe {
428 bindings::dma_fence_remove_callback(self.fence.as_raw(), self.callback_foreign.get())
429 };
430
431 // SAFETY: This is literally the drop implementation, so no one has
432 // dropped this so far; so we can do it now.
433 unsafe { ManuallyDrop::<T>::drop(self.project().callback) };
434 }
435}
436
437// SAFETY: FenceCallbackRegistration can be sent between threads.
438unsafe impl<T: FenceCallback> Send for FenceCallbackRegistration<T> {}
439
440// SAFETY: &FenceCallbackRegistration can be shared between threads if &T can.
441unsafe impl<T: FenceCallback> Sync for FenceCallbackRegistration<T> where T: Sync {}
442
443/// The receiving counterpart of a [`DriverFence`].
444///
445/// The Rust DMA fence implementation has a dualistic design: [`DriverFence`]s
446/// are the producer-side, intended to be always owned by only one party. That
447/// party has the monopoly on signaling the fence.
448///
449/// A [`Fence`] is the counterpart for consumers. Thus, [`Fence`]s are always
450/// refcounted and can shared with an arbitrary number of parties, including
451/// userspace. A [`Fence`] can only be used for actions such as checking the
452/// fence's status or for registering callbacks on it.
453///
454/// Once the associated [`DriverFence`] signals, all
455/// [`FenceCallbackRegistration`]s registered on the [`Fence`] will be executed.
456///
457/// A [`Fence`] can arbitrarily outlive its [`DriverFence`] and the
458/// [`FenceContext`]. Signaling a [`DriverFence`] decouples it from its
459/// [`Fence`]s.
460#[repr(transparent)]
461pub struct Fence {
462 /// The actual dma_fence passed to C.
463 inner: Opaque<bindings::dma_fence>,
464}
465
466/// Guard helper for locking within this module.
467///
468/// Its only purpose for now is to avoid a number of unsafe lock-unlock cycles.
469/// It is never used outside of this module.
470// TODO: This should be made more canonical, probably by basing it on a
471// SpinLockIrqGuard once available.
472struct FenceGuard<'a> {
473 inner: &'a Fence,
474 flags: usize,
475}
476
477impl<'a> Deref for FenceGuard<'a> {
478 type Target = &'a Fence;
479
480 fn deref(&self) -> &Self::Target {
481 &self.inner
482 }
483}
484
485impl Drop for FenceGuard<'_> {
486 fn drop(&mut self) {
487 // SAFETY: `fence` is valid because `self` is valid. `flag_ptr` is
488 // merely a pointer to an integer, which lives as long as this function.
489 // When a `FenceGuard` exists, the lock has been taken by definition.
490 unsafe { bindings::dma_fence_unlock_irqrestore(self.as_raw(), &raw mut self.flags) };
491 }
492}
493
494// SAFETY: Fences are literally designed to be shared between threads.
495unsafe impl Send for Fence {}
496// SAFETY: Fences are literally designed to be shared between threads.
497unsafe impl Sync for Fence {}
498
499impl Fence {
500 /// Check whether the fence was signaled at the moment of the function call.
501 ///
502 /// Note that this can return `true` for a [`Fence`] whose [`DriverFence`]
503 /// has not yet been dropped. The reason is that the fence ops callbacks can
504 /// cause the fence to get signaled by the C backend.
505 #[inline]
506 pub fn is_signaled(&self) -> bool {
507 // We should not use `dma_fence_is_signaled_locked()` here, because
508 // according to the C backend's recommendations, that function is
509 // problematic and we should avoid calling that function with a lock
510 // held.
511
512 // SAFETY: Inner `fence` is valid because `self` is valid.
513 let ret = unsafe { bindings::dma_fence_is_signaled(self.as_raw()) };
514
515 // To be as robust as possible for the future we guarantee that an API
516 // caller can 100% rely on the signaling being completed (i.e., all
517 // fence callbacks ran), so we have to take the lock.
518 //
519 // The reason is that the C dma_fence backend currently does not
520 // carefully synchronize the `dma_fence_is_signaled()` function with the
521 // proper spinlock. This can lead to the function returning `true` while
522 // fence callbacks are still being executed. This can be mitigated by
523 // guarding the entire function with the spinlock.
524 //
525 // The fundamental reason is that the C backend currently does guard
526 // setting of the fence's signaled-bit with the fence's spinlock, but
527 // reading is done locklessly.
528 //
529 // See commit c8a5d5ea3ba6a.
530 let _ = self.lock();
531
532 ret
533 }
534
535 /// Lock the fence. A helper only to be used internally in this module.
536 fn lock(&self) -> FenceGuard<'_> {
537 let mut guard = FenceGuard {
538 inner: self,
539 flags: 0,
540 };
541
542 // SAFETY: `fence` is valid because `self` is valid. `flag_ptr` is
543 // merely a pointer to an integer, whose lifetime is tied to the guard
544 // object.
545 unsafe { bindings::dma_fence_lock_irqsave(self.as_raw(), &raw mut guard.flags) };
546
547 guard
548 }
549
550 /// Get the fence's sequence number.
551 #[inline]
552 pub fn seqno(&self) -> u64 {
553 // SAFETY: Valid because `self` is valid.
554 unsafe { (*self.as_raw()).seqno }
555 }
556
557 fn as_raw(&self) -> *mut bindings::dma_fence {
558 self.inner.get()
559 }
560
561 /// Create a [`Fence`] from a raw C [`bindings::dma_fence`].
562 ///
563 /// # Safety
564 ///
565 /// `ptr` must point to an initialized fence that is embedded into a [`Fence`].
566 #[inline]
567 pub unsafe fn from_raw<'a>(ptr: *mut bindings::dma_fence) -> &'a Self {
568 // SAFETY: Safe as per the function's overall safety requirements.
569 unsafe { &*ptr.cast() }
570 }
571}
572
573// SAFETY: These implement the C backends refcounting methods which are proven
574// to work correctly.
575unsafe impl AlwaysRefCounted for Fence {
576 fn inc_ref(&self) {
577 // SAFETY: `self.as_raw()` is a pointer to a valid `struct dma_fence`.
578 unsafe { bindings::dma_fence_get(self.as_raw()) }
579 }
580
581 unsafe fn dec_ref(ptr: NonNull<Self>) {
582 // SAFETY: `ptr` is never a NULL pointer; and when `dec_ref()` is called
583 // the fence is by definition still valid.
584 let fence = unsafe { (*ptr.as_ptr()).inner.get() };
585
586 // SAFETY: `fence` was created validly above. When `dec_ref()` is called,
587 // there is by definition still a reference alive that can be put.
588 unsafe { bindings::dma_fence_put(fence) }
589 }
590}
591
592// Necessary to guarantee that `inner` always comes first and can be freed by C.
593// Also useful for using casts instead of container_of().
594#[repr(C)]
595#[pin_data]
596struct DriverFenceData<'a, T: Send + Sync + FenceContextOps> {
597 #[pin]
598 /// The inner fence.
599 // Must always be the first member so that unsafe casting works; but also
600 // necessary so that the C backend can free the allocation (coming from our
601 // Rust code) with kfree_rcu().
602 inner: Fence,
603 /// Callback head for dropping this in a deferred manner through RCU.
604 rcu_head: bindings::callback_head,
605 /// Reference to access the FenceContext.
606 fctx: &'a FenceContext<T>,
607 /// The API user's data. It is essential that the data only performs
608 /// operations legal in atomic context in its [`Drop`] implementation.
609 #[pin]
610 data: T::FenceDataType,
611}
612
613/// A synchronization primitive mainly for GPU drivers.
614///
615/// The Rust DMA fence implementation has a dualistic design: [`DriverFence`]s
616/// are the producer-side, intended to be always owned by only one party. That
617/// party has the monopoly on signaling the fence.
618///
619/// A [`Fence`] is the counterpart for consumers. Thus, [`Fence`]s are always
620/// refcounted and can be shared with an arbitrary number of parties, including
621/// userspace. A [`Fence`] can only be used for actions such as checking the
622/// fence's status or for registering callbacks on it.
623///
624/// Once the associated [`DriverFence`] signals, all
625/// [`FenceCallbackRegistration`]s registered on a [`Fence`] will be executed.
626///
627/// A [`Fence`] can arbitrarily outlive its [`DriverFence`] and the
628/// [`FenceContext`]. Signaling a [`DriverFence`] decouples it from its
629/// [`Fence`]s.
630///
631/// It is crucial that a [`DriverFence`] always correctly represents the state
632/// of the associated job on the hardware. Especially, it is strictly necessary
633/// that the owner ensures that all [`DriverFence`]s eventually get signaled.
634/// As a last resort, a [`DriverFence`] will signal itself if it drops
635/// unsignaled and print a warning.
636///
637/// This design intends to implement the [`bindings::dma_fence_ops`] in such a
638/// way that the driver-data necessary to implement the callback's functionality
639/// resides in the [`FenceContext`]. Thus, a [`DriverFence`] contains a
640/// reference to the context, which can be accessed in the callbacks. The
641/// implementation, therefore, ensures that a [`DriverFence`] cannot outlive its
642/// [`FenceContext`]. Unfortunately, this can be circumvented under certain
643/// circumstances in Rust (e.g., usage of [`core::mem::forget`]).
644///
645/// In the unlikely case of such violations, a panic is thrown.
646///
647/// # Examples
648///
649/// ```
650/// use kernel::{
651/// dma_buf::{
652/// DriverFence,
653/// FenceContext,
654/// FenceContextOps,
655/// FenceCallback,
656/// FenceCallbackRegistration,
657/// },
658/// str::CString,
659/// sync::aref::ARef, //
660/// };
661/// use core::fmt::Display;
662///
663/// struct CallbackData { }
664///
665/// impl FenceCallback for CallbackData {
666/// fn on_signal(&mut self) {
667/// pr_info!("DmaFence callback executed.\n");
668/// }
669/// }
670///
671/// #[pin_data]
672/// struct FenceContextData {}
673///
674/// impl FenceContextData {
675/// fn new() -> impl PinInit<Self> {
676/// pin_init!(Self {})
677/// }
678/// }
679///
680/// impl FenceContextOps for FenceContextData {
681/// type FenceDataType = FenceData;
682/// }
683///
684/// let fctx_data = FenceContextData::new();
685///
686///
687/// let mut fctx = KBox::pin_init(
688/// FenceContext::new(0, c"dummy_driver", c"dummy_timeline", fctx_data),
689/// GFP_KERNEL
690/// )?;
691///
692/// struct FenceData {
693/// data: CString,
694/// }
695///
696/// let fence_data = FenceData { data: c"dummy_data".try_into()? };
697///
698/// let fence_alloc = fctx.new_fence_allocation(fence_data)?;
699/// let mut fence = fence_alloc.new_fence();
700///
701/// let cb_data = CallbackData { };
702/// let waiting_fence = ARef::from(fence.as_fence());
703/// // SAFETY: `cb_data` is not forgotten.
704/// let cb_reg = unsafe { FenceCallbackRegistration::new(&waiting_fence, cb_data) };
705/// let cb_reg = KBox::pin_init(cb_reg, GFP_KERNEL)?;
706///
707/// // TODO signalling guards
708/// assert_eq!(waiting_fence.is_signaled(), false);
709/// fence.signal(Ok(()));
710/// assert_eq!(waiting_fence.is_signaled(), true);
711///
712/// Ok::<(), Error>(())
713/// ```
714pub struct DriverFence<'a, T: Send + Sync + FenceContextOps> {
715 /// The actual content of the fence. Lives in a [`NonNull`] so that its
716 /// memory can be managed independently. Valid until both the [`DriverFence`]
717 /// and all associated [`Fence`]s have disappeared.
718 data: NonNull<DriverFenceData<'a, T>>,
719}
720
721/// A pre-prepared DMA fence, carrying the user's data and the memory it and the
722/// fence reside in. Only useful for creating a [`DriverFence`]. Splitting
723/// allocation and full initialization is necessary because fences cannot be
724/// allocated dynamically in some circumstances (deadlock).
725pub struct DriverFenceAllocation<'a, T: Send + Sync + FenceContextOps> {
726 /// The memory for the actual content of the fence.
727 /// Handed over to a [`DriverFence`], or deallocated once the
728 /// [`DriverFenceAllocation`] drops.
729 data: KBox<DriverFenceData<'a, T>>,
730 /// Reference for the ops for the associated [`FenceContext`]
731 ops: &'static bindings::dma_fence_ops,
732}
733
734impl<'a, T: Send + Sync + FenceContextOps> DriverFenceAllocation<'a, T> {
735 /// Create a new [`DriverFence`], the signalable counterpart of a [`Fence`].
736 ///
737 /// This increments the sequence number in the associated [`FenceContext`].
738 pub fn new_fence(self) -> DriverFence<'a, T> {
739 // We feed the C dma_fence backend a NULL for the spinlock so that it
740 // uses per-fence locks automatically.
741 let null_ptr: *mut bindings::spinlock = ptr::null_mut();
742 let seqno = self.data.fctx.next_seqno();
743 let fence_ptr = self.as_raw();
744 // SAFETY: `fence_ptr` has been created directly above. It will live
745 // at least as long as `Self`. The same applies to `&Self::OPS`.
746 unsafe {
747 bindings::dma_fence_init(fence_ptr, self.ops, null_ptr, self.data.fctx.nr, seqno)
748 };
749
750 self.data.fctx.nr_of_unsignaled_fences.fetch_add(1, Relaxed);
751
752 // A `DriverFenceAllocation`'s purpose is to carry allocated memory, so
753 // that `DriverFence`s can always be created without allocating. In this
754 // method, ownership over that memory is transferred to the new
755 // `DriverFence` and managed through refcounting. The C dma_fence
756 // backend will ultimately free the memory once the refcount reaches 0.
757 let ptr = KBox::into_raw(self.data);
758 // SAFETY: `ptr` was just created validly directly above.
759 let ptr = unsafe { NonNull::new_unchecked(ptr) };
760
761 DriverFence { data: ptr }
762 }
763
764 fn as_raw(&self) -> *mut bindings::dma_fence {
765 self.data.inner.inner.get()
766 }
767}
768
769impl<'a, T: Send + Sync + FenceContextOps> DriverFence<'a, T> {
770 fn as_raw(&self) -> *mut bindings::dma_fence {
771 // SAFETY: Valid because `self` is valid.
772 let fence_data = unsafe { &*self.data.as_ptr() };
773
774 fence_data.inner.inner.get()
775 }
776
777 /// Create a [`DriverFence`] from a raw pointer to a [`bindings::dma_fence`].
778 ///
779 /// # Safety
780 ///
781 /// `ptr` must be a valid pointer to a `dma_fence` that was obtained through
782 /// a [`DriverFence`] with matching generic data for both fence and associated
783 /// [`FenceContext`].
784 unsafe fn from_raw(ptr: *mut bindings::dma_fence) -> Self {
785 let opaque_fence = Opaque::cast_from(ptr);
786
787 // SAFETY: Safe due to the function's overall safety requirements.
788 let fence_ptr = unsafe { container_of!(opaque_fence, Fence, inner) };
789
790 // DriverFenceData is `repr(C)` and a Fence is its first member.
791 let fence_data_ptr = fence_ptr as *mut DriverFenceData<'a, T>;
792
793 // SAFETY: `fence_data_ptr` was created validly above.
794 let data = unsafe { NonNull::new_unchecked(fence_data_ptr) };
795
796 Self { data }
797 }
798
799 /// Return the underlying [`Fence`].
800 #[inline]
801 pub fn as_fence(&self) -> &Fence {
802 // SAFETY: `self` is by definition still valid, and it cannot drop until
803 // this new reference is gone.
804 unsafe { Fence::from_raw(self.as_raw()) }
805 }
806
807 /// Signal the fence. This will invoke all registered callbacks.
808 pub fn signal(self, res: Result) {
809 let fence = self.as_fence().lock();
810
811 // SAFETY: `fence` is valid because `self` is valid. The lock must be
812 // held, which we acquired directly above.
813 if !unsafe { bindings::dma_fence_test_signaled_flag(fence.as_raw()) } {
814 if let Err(err) = res {
815 // SAFETY: `fence` is valid because `self` is valid. The fence
816 // must not have been signaled yet, which we check directly above.
817 unsafe { bindings::dma_fence_set_error(fence.as_raw(), err.to_errno()) };
818 }
819 // SAFETY: `fence` is valid because `self` is valid. The lock must
820 // be held, which we acquired above.
821 unsafe { bindings::dma_fence_signal_locked(fence.as_raw()) };
822 }
823
824 // SAFETY: `self.data` is valid because `self` is valid.
825 let fctx = unsafe { self.data.as_ref().fctx };
826 let _ = fctx.nr_of_unsignaled_fences.fetch_sub(1, Relaxed);
827 }
828}
829
830// SAFETY: Fences are literally designed to be shared between threads.
831unsafe impl<'a, T: Send + Sync + FenceContextOps> Send for DriverFence<'a, T> {}
832// SAFETY: Fences are literally designed to be shared between threads.
833unsafe impl<'a, T: Send + Sync + FenceContextOps> Sync for DriverFence<'a, T> {}
834
835impl<'a, T: Send + Sync + FenceContextOps> Deref for DriverFence<'a, T> {
836 type Target = T::FenceDataType;
837
838 fn deref(&self) -> &Self::Target {
839 // SAFETY: Thanks to refcounting, `data` is always valid as long as `self` is.
840 let data = unsafe { &*self.data.as_ptr() };
841
842 &data.data
843 }
844}
845
846/// A borrow wrapper for [`DriverFence`]. Implements [`Deref`].
847pub struct DriverFenceBorrow<'a, T: Send + Sync + FenceContextOps> {
848 driver_fence: ManuallyDrop<DriverFence<'a, T>>,
849 _lifetime: PhantomData<&'a T>,
850}
851
852impl<'a, T: Send + Sync + FenceContextOps> Deref for DriverFenceBorrow<'a, T> {
853 type Target = DriverFence<'a, T>;
854
855 fn deref(&self) -> &Self::Target {
856 self.driver_fence.deref()
857 }
858}
859
860// SAFETY: The Rust dma_fence abstractions are already designed around the inner
861// C `dma_fence`, which can serve safely as the identification point when being
862// owned by C. Moreover, safety is ensured by not dropping `DriverFence` and by
863// only allowing operations without side effects on the Borrowed type.
864unsafe impl<T: Send + Sync + FenceContextOps> ForeignOwnable for DriverFence<'_, T> {
865 type Borrowed<'a>
866 = DriverFenceBorrow<'a, T>
867 where
868 Self: 'a;
869 type BorrowedMut<'a>
870 = DriverFenceBorrow<'a, T>
871 where
872 Self: 'a;
873
874 const FOREIGN_ALIGN: usize = core::mem::align_of::<bindings::dma_fence>();
875
876 fn into_foreign(self) -> *mut c_void {
877 let fence = self;
878
879 let ptr = fence.as_raw();
880
881 // DriverFence must not drop.
882 let _ = ManuallyDrop::new(fence);
883
884 ptr.cast()
885 }
886
887 unsafe fn from_foreign(ptr: *mut c_void) -> Self {
888 // SAFETY: Safe because the trait implementation only invokes this with
889 // a valid `ptr`, associated to a `DriverFence` with matching generic data.
890 unsafe { Self::from_raw(ptr.cast()) }
891 }
892
893 unsafe fn borrow<'a>(ptr: *mut c_void) -> Self::Borrowed<'a>
894 where
895 Self: 'a,
896 {
897 // SAFETY: The trait implementation ensures that `ptr` always resides
898 // within a [`Fence`] within a [`DriverFenceData`].
899 let driver_fence = unsafe { Self::from_raw(ptr.cast()) };
900
901 let driver_fence = ManuallyDrop::new(driver_fence);
902
903 DriverFenceBorrow {
904 driver_fence,
905 _lifetime: PhantomData,
906 }
907 }
908
909 unsafe fn borrow_mut<'a>(ptr: *mut c_void) -> Self::BorrowedMut<'a>
910 // FIXME: The bound below and the one above in `borrow` should actually be
911 // unnecessary since the compiler should be able to completely derive all
912 // necessary information automatically. There is currently a compiler bug
913 // preventing that, though:
914 //
915 // https://github.com/rust-lang/rust/issues/155430.
916 //
917 // (Help to) fix the compiler bug and remove the bounds afterwards.
918 where
919 Self: 'a,
920 {
921 // SAFETY: The trait implementation ensures that `ptr` always resides
922 // within a [`Fence`] within a [`DriverFenceData`].
923 let driver_fence = unsafe { Self::from_raw(ptr.cast()) };
924
925 let driver_fence = ManuallyDrop::new(driver_fence);
926
927 DriverFenceBorrow {
928 driver_fence,
929 _lifetime: PhantomData,
930 }
931 }
932}
933
934impl<'a, T: Send + Sync + FenceContextOps> Drop for DriverFence<'a, T> {
935 fn drop(&mut self) {
936 let guard = self.as_fence().lock();
937
938 // Use dma_fence_test_signaled_flag() instead of
939 // dma_fence_is_signaled_locked() because the C backend wants to get rid
940 // of the latter.
941
942 // SAFETY: `guard` is valid until the `call_rcu()` below.
943 let signaled: bool = unsafe { bindings::dma_fence_test_signaled_flag(guard.as_raw()) };
944 if !signaled {
945 pr_err!("DriverFence drops unsignaled. Danger of memory corruption!\n");
946 // SAFETY: `guard` is valid until the `call_rcu()` below. The fence
947 // must not have been signaled yet, which we check directly above.
948 unsafe { bindings::dma_fence_set_error(guard.as_raw(), ECANCELED.to_errno()) };
949 // SAFETY: `guard` is valid until the `call_rcu()` below. The lock
950 // must be held, which we acquired above.
951 unsafe { bindings::dma_fence_signal_locked(guard.as_raw()) };
952
953 // SAFETY: `self.data` is valid because `self` is valid.
954 let fctx = unsafe { self.data.as_ref().fctx };
955 let _ = fctx.nr_of_unsignaled_fences.fetch_sub(1, Relaxed);
956 }
957 drop(guard);
958
959 // `DriverFenceData` could be accessed through some dma_fence
960 // callbacks right now. Access is being revoked in principle above by
961 // signaling the fence, but since the C backend does not guarantee
962 // perfect full synchronization, we have to wait for one grace period to
963 // ensure that all accessors of `DriverFenceData` (through the
964 // dma_fence_ops accessible through a `Fence`) are gone.
965
966 if !core::mem::needs_drop::<T::FenceDataType>() {
967 // SAFETY: Once a `DriverFence` is initialized, the inner `fence` is
968 // valid and initialized. It is valid until the refcount drops to 0,
969 // which can earliest happen once we drop the `DriverFence`'s
970 // reference here.
971 unsafe { bindings::dma_fence_put(self.as_raw()) };
972 return;
973 }
974
975 // SAFETY: Valid because `self` is valid.
976 let rcu_head_ptr = unsafe { &raw mut (*self.data.as_ptr()).rcu_head };
977
978 // SAFETY: `call_rcu()` is always safe to be called. `rcu_head_ptr` was
979 // created validly above. The module must perform a `synchronize_rcu()`
980 // or `rcu_barrier()` call to guard against module unload.
981 unsafe { bindings::call_rcu(rcu_head_ptr, Some(drop_driver_fence_data::<T>)) };
982 }
983}
984
985// TODO:
986// The entire call_rcu() mechanism in the drop above and the code below would be
987// unnecessary if C's dma_fence_signal() could be reworked in a way that after it
988// ran, the caller knows that no fence_ops callbacks can be running anymore.
989// In other words, if the dma_fence backend would use its spinlock for full
990// synchronization.
991//
992// Then we could move the drop_in_place() and dma_fence_put() upwards into the
993// drop() implementation and call it a day.
994
995/// Finally really drop this `DriverFence<T>`
996///
997/// # Safety
998///
999/// `head` references the `rcu_head` field of an `DriverFenceData<T>`. All
1000/// accessors to that `DriverFenceData<T>` must be gone by now. This must be
1001/// ensured by signalling the associated `DriverFence<T>` and then waiting
1002/// for a grace period until calling this function here.
1003unsafe extern "C" fn drop_driver_fence_data<T: Send + Sync + FenceContextOps>(
1004 head: *mut bindings::callback_head,
1005) {
1006 // SAFETY: Caller provides a pointer to the `rcu_head` field of a `DriverFenceData<C>`.
1007 let fence_data = unsafe { container_of!(head, DriverFenceData<'_, T>, rcu_head) };
1008
1009 // SAFETY: `fence_data` was created validly above. All the fence's data will
1010 // only drop below, but the raw pointer to the raw C `dma_fence` remains
1011 // valid because the reference count is only decremented at the end of the
1012 // function.
1013 let fence = unsafe { (*fence_data).inner.inner.get() };
1014
1015 // SAFETY: `fence_data` was created validly above. The user has already
1016 // dropped the only conventional accessor to the user data, the `DriverFence`,
1017 // one grace period ago. All accessors are gone now.
1018 unsafe { drop_in_place(&raw mut (*fence_data).data) };
1019
1020 // The inner `Fence` explicitly does not get dropped because there may be
1021 // many more users / consumers, each holding their own reference.
1022
1023 // SAFETY: Once a `DriverFence` is initialized, the inner `fence` is valid
1024 // and initialized. It is valid until the refcount drops to 0, which can
1025 // earliest happen once we drop the `DriverFence`'s reference here.
1026 unsafe { bindings::dma_fence_put(fence) };
1027
1028 // The actual memory the data associated with a `DriverFence` lives in
1029 // gets freed by the C dma_fence backend once the fence's refcount reaches 0.
1030}