Skip to main content

kernel/
dma.rs

1// SPDX-License-Identifier: GPL-2.0
2
3//! Direct memory access (DMA).
4//!
5//! C header: [`include/linux/dma-mapping.h`](srctree/include/linux/dma-mapping.h)
6
7use crate::{
8    bindings,
9    debugfs,
10    device::{
11        self,
12        Bound,
13        Core, //
14    },
15    error::to_result,
16    fs::file,
17    prelude::*,
18    ptr::KnownSize,
19    sync::aref::ARef,
20    transmute::{
21        AsBytes,
22        FromBytes, //
23    }, //
24    uaccess::UserSliceWriter,
25};
26use core::{
27    ops::{
28        Deref,
29        DerefMut, //
30    },
31    ptr::NonNull, //
32};
33
34/// DMA address type.
35///
36/// Represents a bus address used for Direct Memory Access (DMA) operations.
37///
38/// This is an alias of the kernel's `dma_addr_t`, which may be `u32` or `u64` depending on
39/// `CONFIG_ARCH_DMA_ADDR_T_64BIT`.
40///
41/// Note that this may be `u64` even on 32-bit architectures.
42pub type DmaAddress = bindings::dma_addr_t;
43
44/// Trait to be implemented by DMA capable bus devices.
45///
46/// The [`dma::Device`](Device) trait should be implemented by bus specific device representations,
47/// where the underlying bus is DMA capable, such as:
48#[cfg_attr(CONFIG_PCI, doc = "* [`pci::Device`](kernel::pci::Device)")]
49/// * [`platform::Device`](::kernel::platform::Device)
50pub trait Device: AsRef<device::Device<Core>> {
51    /// Set up the device's DMA streaming addressing capabilities.
52    ///
53    /// This method is usually called once from `probe()` as soon as the device capabilities are
54    /// known.
55    ///
56    /// # Safety
57    ///
58    /// This method must not be called concurrently with any DMA allocation or mapping primitives,
59    /// such as [`Coherent::zeroed`].
60    unsafe fn dma_set_mask(&self, mask: DmaMask) -> Result {
61        // SAFETY:
62        // - By the type invariant of `device::Device`, `self.as_ref().as_raw()` is valid.
63        // - The safety requirement of this function guarantees that there are no concurrent calls
64        //   to DMA allocation and mapping primitives using this mask.
65        to_result(unsafe { bindings::dma_set_mask(self.as_ref().as_raw(), mask.value()) })
66    }
67
68    /// Set up the device's DMA coherent addressing capabilities.
69    ///
70    /// This method is usually called once from `probe()` as soon as the device capabilities are
71    /// known.
72    ///
73    /// # Safety
74    ///
75    /// This method must not be called concurrently with any DMA allocation or mapping primitives,
76    /// such as [`Coherent::zeroed`].
77    unsafe fn dma_set_coherent_mask(&self, mask: DmaMask) -> Result {
78        // SAFETY:
79        // - By the type invariant of `device::Device`, `self.as_ref().as_raw()` is valid.
80        // - The safety requirement of this function guarantees that there are no concurrent calls
81        //   to DMA allocation and mapping primitives using this mask.
82        to_result(unsafe { bindings::dma_set_coherent_mask(self.as_ref().as_raw(), mask.value()) })
83    }
84
85    /// Set up the device's DMA addressing capabilities.
86    ///
87    /// This is a combination of [`Device::dma_set_mask`] and [`Device::dma_set_coherent_mask`].
88    ///
89    /// This method is usually called once from `probe()` as soon as the device capabilities are
90    /// known.
91    ///
92    /// # Safety
93    ///
94    /// This method must not be called concurrently with any DMA allocation or mapping primitives,
95    /// such as [`Coherent::zeroed`].
96    unsafe fn dma_set_mask_and_coherent(&self, mask: DmaMask) -> Result {
97        // SAFETY:
98        // - By the type invariant of `device::Device`, `self.as_ref().as_raw()` is valid.
99        // - The safety requirement of this function guarantees that there are no concurrent calls
100        //   to DMA allocation and mapping primitives using this mask.
101        to_result(unsafe {
102            bindings::dma_set_mask_and_coherent(self.as_ref().as_raw(), mask.value())
103        })
104    }
105
106    /// Set the maximum size of a single DMA segment the device may request.
107    ///
108    /// This method is usually called once from `probe()` as soon as the device capabilities are
109    /// known.
110    ///
111    /// # Safety
112    ///
113    /// This method must not be called concurrently with any DMA allocation or mapping primitives,
114    /// such as [`Coherent::zeroed`].
115    unsafe fn dma_set_max_seg_size(&self, size: u32) {
116        // SAFETY:
117        // - By the type invariant of `device::Device`, `self.as_ref().as_raw()` is valid.
118        // - The safety requirement of this function guarantees that there are no concurrent calls
119        //   to DMA allocation and mapping primitives using this parameter.
120        unsafe { bindings::dma_set_max_seg_size(self.as_ref().as_raw(), size) }
121    }
122}
123
124/// A DMA mask that holds a bitmask with the lowest `n` bits set.
125///
126/// Use [`DmaMask::new`] or [`DmaMask::try_new`] to construct a value. Values
127/// are guaranteed to never exceed the bit width of `u64`.
128///
129/// This is the Rust equivalent of the C macro `DMA_BIT_MASK()`.
130#[derive(Debug, Clone, Copy, PartialEq, Eq)]
131pub struct DmaMask(u64);
132
133impl DmaMask {
134    /// Constructs a `DmaMask` with the lowest `n` bits set to `1`.
135    ///
136    /// For `n <= 64`, sets exactly the lowest `n` bits.
137    /// For `n > 64`, results in a build error.
138    ///
139    /// # Examples
140    ///
141    /// ```
142    /// use kernel::dma::DmaMask;
143    ///
144    /// let mask0 = DmaMask::new::<0>();
145    /// assert_eq!(mask0.value(), 0);
146    ///
147    /// let mask1 = DmaMask::new::<1>();
148    /// assert_eq!(mask1.value(), 0b1);
149    ///
150    /// let mask64 = DmaMask::new::<64>();
151    /// assert_eq!(mask64.value(), u64::MAX);
152    ///
153    /// // Build failure.
154    /// // let mask_overflow = DmaMask::new::<100>();
155    /// ```
156    #[inline]
157    pub const fn new<const N: u32>() -> Self {
158        let Ok(mask) = Self::try_new(N) else {
159            build_error!("Invalid DMA Mask.");
160        };
161
162        mask
163    }
164
165    /// Constructs a `DmaMask` with the lowest `n` bits set to `1`.
166    ///
167    /// For `n <= 64`, sets exactly the lowest `n` bits.
168    /// For `n > 64`, returns [`EINVAL`].
169    ///
170    /// # Examples
171    ///
172    /// ```
173    /// use kernel::dma::DmaMask;
174    ///
175    /// let mask0 = DmaMask::try_new(0)?;
176    /// assert_eq!(mask0.value(), 0);
177    ///
178    /// let mask1 = DmaMask::try_new(1)?;
179    /// assert_eq!(mask1.value(), 0b1);
180    ///
181    /// let mask64 = DmaMask::try_new(64)?;
182    /// assert_eq!(mask64.value(), u64::MAX);
183    ///
184    /// let mask_overflow = DmaMask::try_new(100);
185    /// assert!(mask_overflow.is_err());
186    /// # Ok::<(), Error>(())
187    /// ```
188    #[inline]
189    pub const fn try_new(n: u32) -> Result<Self> {
190        Ok(Self(match n {
191            0 => 0,
192            1..=64 => u64::MAX >> (64 - n),
193            _ => return Err(EINVAL),
194        }))
195    }
196
197    /// Returns the underlying `u64` bitmask value.
198    #[inline]
199    pub const fn value(&self) -> u64 {
200        self.0
201    }
202}
203
204/// Possible attributes associated with a DMA mapping.
205///
206/// They can be combined with the operators `|`, `&`, and `!`.
207///
208/// Values can be used from the [`attrs`] module.
209///
210/// # Examples
211///
212/// ```
213/// # use kernel::device::{Bound, Device};
214/// use kernel::dma::{attrs::*, Coherent};
215///
216/// # fn test(dev: &Device<Bound>) -> Result {
217/// let attribs = DMA_ATTR_FORCE_CONTIGUOUS | DMA_ATTR_NO_WARN;
218/// let c: Coherent<[u64]> =
219///     Coherent::zeroed_slice_with_attrs(dev, 4, GFP_KERNEL, attribs)?;
220/// # Ok::<(), Error>(()) }
221/// ```
222#[derive(Clone, Copy, PartialEq)]
223#[repr(transparent)]
224pub struct Attrs(u32);
225
226impl Attrs {
227    /// Get the raw representation of this attribute.
228    pub(crate) fn as_raw(self) -> crate::ffi::c_ulong {
229        self.0 as crate::ffi::c_ulong
230    }
231
232    /// Check whether `flags` is contained in `self`.
233    pub fn contains(self, flags: Attrs) -> bool {
234        (self & flags) == flags
235    }
236}
237
238impl core::ops::BitOr for Attrs {
239    type Output = Self;
240    fn bitor(self, rhs: Self) -> Self::Output {
241        Self(self.0 | rhs.0)
242    }
243}
244
245impl core::ops::BitAnd for Attrs {
246    type Output = Self;
247    fn bitand(self, rhs: Self) -> Self::Output {
248        Self(self.0 & rhs.0)
249    }
250}
251
252impl core::ops::Not for Attrs {
253    type Output = Self;
254    fn not(self) -> Self::Output {
255        Self(!self.0)
256    }
257}
258
259/// DMA mapping attributes.
260pub mod attrs {
261    use super::Attrs;
262
263    /// Specifies that reads and writes to the mapping may be weakly ordered, that is that reads
264    /// and writes may pass each other.
265    pub const DMA_ATTR_WEAK_ORDERING: Attrs = Attrs(bindings::DMA_ATTR_WEAK_ORDERING);
266
267    /// Specifies that writes to the mapping may be buffered to improve performance.
268    pub const DMA_ATTR_WRITE_COMBINE: Attrs = Attrs(bindings::DMA_ATTR_WRITE_COMBINE);
269
270    /// Allows platform code to skip synchronization of the CPU cache for the given buffer assuming
271    /// that it has been already transferred to 'device' domain.
272    pub const DMA_ATTR_SKIP_CPU_SYNC: Attrs = Attrs(bindings::DMA_ATTR_SKIP_CPU_SYNC);
273
274    /// Forces contiguous allocation of the buffer in physical memory.
275    pub const DMA_ATTR_FORCE_CONTIGUOUS: Attrs = Attrs(bindings::DMA_ATTR_FORCE_CONTIGUOUS);
276
277    /// Hints DMA-mapping subsystem that it's probably not worth the time to try
278    /// to allocate memory to in a way that gives better TLB efficiency.
279    pub const DMA_ATTR_ALLOC_SINGLE_PAGES: Attrs = Attrs(bindings::DMA_ATTR_ALLOC_SINGLE_PAGES);
280
281    /// This tells the DMA-mapping subsystem to suppress allocation failure reports (similarly to
282    /// `__GFP_NOWARN`).
283    pub const DMA_ATTR_NO_WARN: Attrs = Attrs(bindings::DMA_ATTR_NO_WARN);
284
285    /// Indicates that the buffer is fully accessible at an elevated privilege level (and
286    /// ideally inaccessible or at least read-only at lesser-privileged levels).
287    pub const DMA_ATTR_PRIVILEGED: Attrs = Attrs(bindings::DMA_ATTR_PRIVILEGED);
288
289    /// Indicates that the buffer is MMIO memory.
290    pub const DMA_ATTR_MMIO: Attrs = Attrs(bindings::DMA_ATTR_MMIO);
291}
292
293/// DMA data direction.
294///
295/// Corresponds to the C [`enum dma_data_direction`].
296///
297/// [`enum dma_data_direction`]: srctree/include/linux/dma-direction.h
298#[derive(Copy, Clone, PartialEq, Eq, Debug)]
299#[repr(u32)]
300pub enum DataDirection {
301    /// The DMA mapping is for bidirectional data transfer.
302    ///
303    /// This is used when the buffer can be both read from and written to by the device.
304    /// The cache for the corresponding memory region is both flushed and invalidated.
305    Bidirectional = Self::const_cast(bindings::dma_data_direction_DMA_BIDIRECTIONAL),
306
307    /// The DMA mapping is for data transfer from memory to the device (write).
308    ///
309    /// The CPU has prepared data in the buffer, and the device will read it.
310    /// The cache for the corresponding memory region is flushed before device access.
311    ToDevice = Self::const_cast(bindings::dma_data_direction_DMA_TO_DEVICE),
312
313    /// The DMA mapping is for data transfer from the device to memory (read).
314    ///
315    /// The device will write data into the buffer for the CPU to read.
316    /// The cache for the corresponding memory region is invalidated before CPU access.
317    FromDevice = Self::const_cast(bindings::dma_data_direction_DMA_FROM_DEVICE),
318
319    /// The DMA mapping is not for data transfer.
320    ///
321    /// This is primarily for debugging purposes. With this direction, the DMA mapping API
322    /// will not perform any cache coherency operations.
323    None = Self::const_cast(bindings::dma_data_direction_DMA_NONE),
324}
325
326impl DataDirection {
327    /// Casts the bindgen-generated enum type to a `u32` at compile time.
328    ///
329    /// This function will cause a compile-time error if the underlying value of the
330    /// C enum is out of bounds for `u32`.
331    const fn const_cast(val: bindings::dma_data_direction) -> u32 {
332        // CAST: The C standard allows compilers to choose different integer types for enums.
333        // To safely check the value, we cast it to a wide signed integer type (`i128`)
334        // which can hold any standard C integer enum type without truncation.
335        let wide_val = val as i128;
336
337        // Check if the value is outside the valid range for the target type `u32`.
338        // CAST: `u32::MAX` is cast to `i128` to match the type of `wide_val` for the comparison.
339        if wide_val < 0 || wide_val > u32::MAX as i128 {
340            // Trigger a compile-time error in a const context.
341            build_error!("C enum value is out of bounds for the target type `u32`.");
342        }
343
344        // CAST: This cast is valid because the check above guarantees that `wide_val`
345        // is within the representable range of `u32`.
346        wide_val as u32
347    }
348}
349
350impl From<DataDirection> for bindings::dma_data_direction {
351    /// Returns the raw representation of [`enum dma_data_direction`].
352    fn from(direction: DataDirection) -> Self {
353        // CAST: `direction as u32` gets the underlying representation of our `#[repr(u32)]` enum.
354        // The subsequent cast to `Self` (the bindgen type) assumes the C enum is compatible
355        // with the enum variants of `DataDirection`, which is a valid assumption given our
356        // compile-time checks.
357        direction as u32 as Self
358    }
359}
360
361/// CPU-owned DMA allocation that can be converted into a device-shared [`Coherent`] object.
362///
363/// Unlike [`Coherent`], a [`CoherentBox`] is guaranteed to be fully owned by the CPU -- its DMA
364/// address is not exposed and it cannot be accessed by a device. This means it can safely be used
365/// like a normal boxed allocation (e.g. direct reads, writes, and mutable slices are all safe).
366///
367/// A typical use is to allocate a [`CoherentBox`], populate it with normal CPU access, and then
368/// convert it into a [`Coherent`] object to share it with the device.
369///
370/// # Examples
371///
372/// `CoherentBox<T>`:
373///
374/// ```
375/// # use kernel::device::{
376/// #     Bound,
377/// #     Device,
378/// # };
379/// use kernel::dma::{attrs::*,
380///     Coherent,
381///     CoherentBox,
382/// };
383///
384/// # fn test(dev: &Device<Bound>) -> Result {
385/// let mut dmem: CoherentBox<u64> = CoherentBox::zeroed(dev, GFP_KERNEL)?;
386/// *dmem = 42;
387/// let dmem: Coherent<u64> = dmem.into();
388/// # Ok::<(), Error>(()) }
389/// ```
390///
391/// `CoherentBox<[T]>`:
392///
393///
394/// ```
395/// # use kernel::device::{
396/// #     Bound,
397/// #     Device,
398/// # };
399/// use kernel::dma::{attrs::*,
400///     Coherent,
401///     CoherentBox,
402/// };
403///
404/// # fn test(dev: &Device<Bound>) -> Result {
405/// let mut dmem: CoherentBox<[u64]> = CoherentBox::zeroed_slice(dev, 4, GFP_KERNEL)?;
406/// dmem.fill(42);
407/// let dmem: Coherent<[u64]> = dmem.into();
408/// # Ok::<(), Error>(()) }
409/// ```
410pub struct CoherentBox<T: KnownSize + ?Sized>(Coherent<T>);
411
412impl<T: AsBytes + FromBytes> CoherentBox<[T]> {
413    /// [`CoherentBox`] variant of [`Coherent::zeroed_slice_with_attrs`].
414    #[inline]
415    pub fn zeroed_slice_with_attrs(
416        dev: &device::Device<Bound>,
417        count: usize,
418        gfp_flags: kernel::alloc::Flags,
419        dma_attrs: Attrs,
420    ) -> Result<Self> {
421        Coherent::zeroed_slice_with_attrs(dev, count, gfp_flags, dma_attrs).map(Self)
422    }
423
424    /// Same as [CoherentBox::zeroed_slice_with_attrs], but with `dma::Attrs(0)`.
425    #[inline]
426    pub fn zeroed_slice(
427        dev: &device::Device<Bound>,
428        count: usize,
429        gfp_flags: kernel::alloc::Flags,
430    ) -> Result<Self> {
431        Self::zeroed_slice_with_attrs(dev, count, gfp_flags, Attrs(0))
432    }
433
434    /// Initializes the element at `i` using the given initializer.
435    ///
436    /// Returns `EINVAL` if `i` is out of bounds.
437    pub fn init_at<E>(&mut self, i: usize, init: impl Init<T, E>) -> Result
438    where
439        Error: From<E>,
440    {
441        if i >= self.0.len() {
442            return Err(EINVAL);
443        }
444
445        let ptr = &raw mut self[i];
446
447        // SAFETY:
448        // - `ptr` is valid, properly aligned, and within this allocation.
449        // - `T: AsBytes + FromBytes` guarantees all bit patterns are valid, so partial writes on
450        //   error cannot leave the element in an invalid state.
451        // - The DMA address has not been exposed yet, so there is no concurrent device access.
452        unsafe { init.__init(ptr)? };
453
454        Ok(())
455    }
456
457    /// Allocates a region of coherent memory of the same size as `data` and initializes it with a
458    /// copy of its contents.
459    ///
460    /// This is the [`CoherentBox`] variant of [`Coherent::from_slice_with_attrs`].
461    ///
462    /// # Examples
463    ///
464    /// ```
465    /// use core::ops::Deref;
466    ///
467    /// # use kernel::device::{Bound, Device};
468    /// use kernel::dma::{
469    ///     attrs::*,
470    ///     CoherentBox
471    /// };
472    ///
473    /// # fn test(dev: &Device<Bound>) -> Result {
474    /// let data = [0u8, 1u8, 2u8, 3u8];
475    /// let c: CoherentBox<[u8]> =
476    ///     CoherentBox::from_slice_with_attrs(dev, &data, GFP_KERNEL, DMA_ATTR_NO_WARN)?;
477    ///
478    /// assert_eq!(c.deref(), &data);
479    /// # Ok::<(), Error>(()) }
480    /// ```
481    pub fn from_slice_with_attrs(
482        dev: &device::Device<Bound>,
483        data: &[T],
484        gfp_flags: kernel::alloc::Flags,
485        dma_attrs: Attrs,
486    ) -> Result<Self>
487    where
488        T: Copy,
489    {
490        let mut slice = Self(Coherent::<T>::alloc_slice_with_attrs(
491            dev,
492            data.len(),
493            gfp_flags,
494            dma_attrs,
495        )?);
496
497        // PANIC: `slice` was created with length `data.len()`.
498        slice.copy_from_slice(data);
499
500        Ok(slice)
501    }
502
503    /// Performs the same functionality as [`CoherentBox::from_slice_with_attrs`], except the
504    /// `dma_attrs` is 0 by default.
505    #[inline]
506    pub fn from_slice(
507        dev: &device::Device<Bound>,
508        data: &[T],
509        gfp_flags: kernel::alloc::Flags,
510    ) -> Result<Self>
511    where
512        T: Copy,
513    {
514        Self::from_slice_with_attrs(dev, data, gfp_flags, Attrs(0))
515    }
516}
517
518impl<T: AsBytes + FromBytes> CoherentBox<T> {
519    /// Same as [`CoherentBox::zeroed_slice_with_attrs`], but for a single element.
520    #[inline]
521    pub fn zeroed_with_attrs(
522        dev: &device::Device<Bound>,
523        gfp_flags: kernel::alloc::Flags,
524        dma_attrs: Attrs,
525    ) -> Result<Self> {
526        Coherent::zeroed_with_attrs(dev, gfp_flags, dma_attrs).map(Self)
527    }
528
529    /// Same as [`CoherentBox::zeroed_slice`], but for a single element.
530    #[inline]
531    pub fn zeroed(dev: &device::Device<Bound>, gfp_flags: kernel::alloc::Flags) -> Result<Self> {
532        Self::zeroed_with_attrs(dev, gfp_flags, Attrs(0))
533    }
534}
535
536impl<T: KnownSize + ?Sized> Deref for CoherentBox<T> {
537    type Target = T;
538
539    #[inline]
540    fn deref(&self) -> &Self::Target {
541        // SAFETY:
542        // - We have not exposed the DMA address yet, so there can't be any concurrent access by a
543        //   device.
544        // - We have exclusive access to `self.0`.
545        unsafe { self.0.as_ref() }
546    }
547}
548
549impl<T: AsBytes + FromBytes + KnownSize + ?Sized> DerefMut for CoherentBox<T> {
550    #[inline]
551    fn deref_mut(&mut self) -> &mut Self::Target {
552        // SAFETY:
553        // - We have not exposed the DMA address yet, so there can't be any concurrent access by a
554        //   device.
555        // - We have exclusive access to `self.0`.
556        unsafe { self.0.as_mut() }
557    }
558}
559
560impl<T: AsBytes + FromBytes + KnownSize + ?Sized> From<CoherentBox<T>> for Coherent<T> {
561    #[inline]
562    fn from(value: CoherentBox<T>) -> Self {
563        value.0
564    }
565}
566
567/// An abstraction of the `dma_alloc_coherent` API.
568///
569/// This is an abstraction around the `dma_alloc_coherent` API which is used to allocate and map
570/// large coherent DMA regions.
571///
572/// A [`Coherent`] instance contains a pointer to the allocated region (in the
573/// processor's virtual address space) and the device address which can be given to the device
574/// as the DMA address base of the region. The region is released once [`Coherent`]
575/// is dropped.
576///
577/// # Invariants
578///
579/// - For the lifetime of an instance of [`Coherent`], the `cpu_addr` is a valid pointer
580///   to an allocated region of coherent memory and `dma_handle` is the DMA address base of the
581///   region.
582/// - The size in bytes of the allocation is equal to size information via pointer.
583// TODO
584//
585// DMA allocations potentially carry device resources (e.g.IOMMU mappings), hence for soundness
586// reasons DMA allocation would need to be embedded in a `Devres` container, in order to ensure
587// that device resources can never survive device unbind.
588//
589// However, it is neither desirable nor necessary to protect the allocated memory of the DMA
590// allocation from surviving device unbind; it would require RCU read side critical sections to
591// access the memory, which may require subsequent unnecessary copies.
592//
593// Hence, find a way to revoke the device resources of a `Coherent`, but not the
594// entire `Coherent` including the allocated memory itself.
595pub struct Coherent<T: KnownSize + ?Sized> {
596    dev: ARef<device::Device>,
597    dma_handle: DmaAddress,
598    cpu_addr: NonNull<T>,
599    dma_attrs: Attrs,
600}
601
602impl<T: KnownSize + ?Sized> Coherent<T> {
603    /// Returns the size in bytes of this allocation.
604    #[inline]
605    pub fn size(&self) -> usize {
606        T::size(self.cpu_addr.as_ptr())
607    }
608
609    /// Returns the raw pointer to the allocated region in the CPU's virtual address space.
610    #[inline]
611    pub fn as_ptr(&self) -> *const T {
612        self.cpu_addr.as_ptr()
613    }
614
615    /// Returns the raw pointer to the allocated region in the CPU's virtual address space as
616    /// a mutable pointer.
617    #[inline]
618    pub fn as_mut_ptr(&self) -> *mut T {
619        self.cpu_addr.as_ptr()
620    }
621
622    /// Returns a DMA handle which may be given to the device as the DMA address base of
623    /// the region.
624    #[inline]
625    pub fn dma_handle(&self) -> DmaAddress {
626        self.dma_handle
627    }
628
629    /// Returns a reference to the data in the region.
630    ///
631    /// # Safety
632    ///
633    /// * Callers must ensure that the device does not read/write to/from memory while the returned
634    ///   slice is live.
635    /// * Callers must ensure that this call does not race with a write to the same region while
636    ///   the returned slice is live.
637    #[inline]
638    pub unsafe fn as_ref(&self) -> &T {
639        // SAFETY: per safety requirement.
640        unsafe { &*self.as_ptr() }
641    }
642
643    /// Returns a mutable reference to the data in the region.
644    ///
645    /// # Safety
646    ///
647    /// * Callers must ensure that the device does not read/write to/from memory while the returned
648    ///   slice is live.
649    /// * Callers must ensure that this call does not race with a read or write to the same region
650    ///   while the returned slice is live.
651    #[expect(clippy::mut_from_ref, reason = "unsafe to use API")]
652    #[inline]
653    pub unsafe fn as_mut(&self) -> &mut T {
654        // SAFETY: per safety requirement.
655        unsafe { &mut *self.as_mut_ptr() }
656    }
657
658    /// Reads the value of `field` and ensures that its type is [`FromBytes`].
659    ///
660    /// # Safety
661    ///
662    /// This must be called from the [`dma_read`] macro which ensures that the `field` pointer is
663    /// validated beforehand.
664    ///
665    /// Public but hidden since it should only be used from [`dma_read`] macro.
666    #[doc(hidden)]
667    pub unsafe fn field_read<F: FromBytes>(&self, field: *const F) -> F {
668        // SAFETY:
669        // - By the safety requirements field is valid.
670        // - Using read_volatile() here is not sound as per the usual rules, the usage here is
671        // a special exception with the following notes in place. When dealing with a potential
672        // race from a hardware or code outside kernel (e.g. user-space program), we need that
673        // read on a valid memory is not UB. Currently read_volatile() is used for this, and the
674        // rationale behind is that it should generate the same code as READ_ONCE() which the
675        // kernel already relies on to avoid UB on data races. Note that the usage of
676        // read_volatile() is limited to this particular case, it cannot be used to prevent
677        // the UB caused by racing between two kernel functions nor do they provide atomicity.
678        unsafe { field.read_volatile() }
679    }
680
681    /// Writes a value to `field` and ensures that its type is [`AsBytes`].
682    ///
683    /// # Safety
684    ///
685    /// This must be called from the [`dma_write`] macro which ensures that the `field` pointer is
686    /// validated beforehand.
687    ///
688    /// Public but hidden since it should only be used from [`dma_write`] macro.
689    #[doc(hidden)]
690    pub unsafe fn field_write<F: AsBytes>(&self, field: *mut F, val: F) {
691        // SAFETY:
692        // - By the safety requirements field is valid.
693        // - Using write_volatile() here is not sound as per the usual rules, the usage here is
694        // a special exception with the following notes in place. When dealing with a potential
695        // race from a hardware or code outside kernel (e.g. user-space program), we need that
696        // write on a valid memory is not UB. Currently write_volatile() is used for this, and the
697        // rationale behind is that it should generate the same code as WRITE_ONCE() which the
698        // kernel already relies on to avoid UB on data races. Note that the usage of
699        // write_volatile() is limited to this particular case, it cannot be used to prevent
700        // the UB caused by racing between two kernel functions nor do they provide atomicity.
701        unsafe { field.write_volatile(val) }
702    }
703}
704
705impl<T: AsBytes + FromBytes> Coherent<T> {
706    /// Allocates a region of `T` of coherent memory.
707    fn alloc_with_attrs(
708        dev: &device::Device<Bound>,
709        gfp_flags: kernel::alloc::Flags,
710        dma_attrs: Attrs,
711    ) -> Result<Self> {
712        const {
713            assert!(
714                core::mem::size_of::<T>() > 0,
715                "It doesn't make sense for the allocated type to be a ZST"
716            );
717        }
718
719        let mut dma_handle = 0;
720        // SAFETY: Device pointer is guaranteed as valid by the type invariant on `Device`.
721        let addr = unsafe {
722            bindings::dma_alloc_attrs(
723                dev.as_raw(),
724                core::mem::size_of::<T>(),
725                &mut dma_handle,
726                gfp_flags.as_raw(),
727                dma_attrs.as_raw(),
728            )
729        };
730        let cpu_addr = NonNull::new(addr.cast()).ok_or(ENOMEM)?;
731        // INVARIANT:
732        // - We just successfully allocated a coherent region which is adequately sized for `T`,
733        //   hence the cpu address is valid.
734        // - We also hold a refcounted reference to the device.
735        Ok(Self {
736            dev: dev.into(),
737            dma_handle,
738            cpu_addr,
739            dma_attrs,
740        })
741    }
742
743    /// Allocates a region of type `T` of coherent memory.
744    ///
745    /// # Examples
746    ///
747    /// ```
748    /// # use kernel::device::{
749    /// #     Bound,
750    /// #     Device,
751    /// # };
752    /// use kernel::dma::{
753    ///     attrs::*,
754    ///     Coherent,
755    /// };
756    ///
757    /// # fn test(dev: &Device<Bound>) -> Result {
758    /// let c: Coherent<[u64; 4]> =
759    ///     Coherent::zeroed_with_attrs(dev, GFP_KERNEL, DMA_ATTR_NO_WARN)?;
760    /// # Ok::<(), Error>(()) }
761    /// ```
762    #[inline]
763    pub fn zeroed_with_attrs(
764        dev: &device::Device<Bound>,
765        gfp_flags: kernel::alloc::Flags,
766        dma_attrs: Attrs,
767    ) -> Result<Self> {
768        Self::alloc_with_attrs(dev, gfp_flags | __GFP_ZERO, dma_attrs)
769    }
770
771    /// Performs the same functionality as [`Coherent::zeroed_with_attrs`], except the
772    /// `dma_attrs` is 0 by default.
773    #[inline]
774    pub fn zeroed(dev: &device::Device<Bound>, gfp_flags: kernel::alloc::Flags) -> Result<Self> {
775        Self::zeroed_with_attrs(dev, gfp_flags, Attrs(0))
776    }
777
778    /// Same as [`Coherent::zeroed_with_attrs`], but instead of a zero-initialization the memory is
779    /// initialized with `init`.
780    pub fn init_with_attrs<E>(
781        dev: &device::Device<Bound>,
782        gfp_flags: kernel::alloc::Flags,
783        dma_attrs: Attrs,
784        init: impl Init<T, E>,
785    ) -> Result<Self>
786    where
787        Error: From<E>,
788    {
789        let dmem = Self::alloc_with_attrs(dev, gfp_flags, dma_attrs)?;
790        let ptr = dmem.as_mut_ptr();
791
792        // SAFETY:
793        // - `ptr` is valid, properly aligned, and points to exclusively owned memory.
794        // - If `__init` fails, `self` is dropped, which safely frees the underlying `Coherent`'s
795        //   DMA memory. `T: AsBytes + FromBytes` ensures there are no complex `Drop` requirements
796        //   we are bypassing.
797        unsafe { init.__init(ptr)? };
798
799        Ok(dmem)
800    }
801
802    /// Same as [`Coherent::zeroed`], but instead of a zero-initialization the memory is initialized
803    /// with `init`.
804    #[inline]
805    pub fn init<E>(
806        dev: &device::Device<Bound>,
807        gfp_flags: kernel::alloc::Flags,
808        init: impl Init<T, E>,
809    ) -> Result<Self>
810    where
811        Error: From<E>,
812    {
813        Self::init_with_attrs(dev, gfp_flags, Attrs(0), init)
814    }
815
816    /// Allocates a region of `[T; len]` of coherent memory.
817    fn alloc_slice_with_attrs(
818        dev: &device::Device<Bound>,
819        len: usize,
820        gfp_flags: kernel::alloc::Flags,
821        dma_attrs: Attrs,
822    ) -> Result<Coherent<[T]>> {
823        const {
824            assert!(
825                core::mem::size_of::<T>() > 0,
826                "It doesn't make sense for the allocated type to be a ZST"
827            );
828        }
829
830        // `dma_alloc_attrs` cannot handle zero-length allocation, bail early.
831        if len == 0 {
832            Err(EINVAL)?;
833        }
834
835        let size = core::mem::size_of::<T>().checked_mul(len).ok_or(ENOMEM)?;
836        let mut dma_handle = 0;
837        // SAFETY: Device pointer is guaranteed as valid by the type invariant on `Device`.
838        let addr = unsafe {
839            bindings::dma_alloc_attrs(
840                dev.as_raw(),
841                size,
842                &mut dma_handle,
843                gfp_flags.as_raw(),
844                dma_attrs.as_raw(),
845            )
846        };
847        let cpu_addr = NonNull::slice_from_raw_parts(NonNull::new(addr.cast()).ok_or(ENOMEM)?, len);
848        // INVARIANT:
849        // - We just successfully allocated a coherent region which is adequately sized for
850        //   `[T; len]`, hence the cpu address is valid.
851        // - We also hold a refcounted reference to the device.
852        Ok(Coherent {
853            dev: dev.into(),
854            dma_handle,
855            cpu_addr,
856            dma_attrs,
857        })
858    }
859
860    /// Allocates a zeroed region of type `T` of coherent memory.
861    ///
862    /// Unlike `Coherent::<[T; N]>::zeroed_with_attrs`, `Coherent::<T>::zeroed_slices` support
863    /// a runtime length.
864    ///
865    /// # Examples
866    ///
867    /// ```
868    /// # use kernel::device::{
869    /// #     Bound,
870    /// #     Device,
871    /// # };
872    /// use kernel::dma::{
873    ///     attrs::*,
874    ///     Coherent,
875    /// };
876    ///
877    /// # fn test(dev: &Device<Bound>) -> Result {
878    /// let c: Coherent<[u64]> =
879    ///     Coherent::zeroed_slice_with_attrs(dev, 4, GFP_KERNEL, DMA_ATTR_NO_WARN)?;
880    /// # Ok::<(), Error>(()) }
881    /// ```
882    #[inline]
883    pub fn zeroed_slice_with_attrs(
884        dev: &device::Device<Bound>,
885        len: usize,
886        gfp_flags: kernel::alloc::Flags,
887        dma_attrs: Attrs,
888    ) -> Result<Coherent<[T]>> {
889        Coherent::alloc_slice_with_attrs(dev, len, gfp_flags | __GFP_ZERO, dma_attrs)
890    }
891
892    /// Performs the same functionality as [`Coherent::zeroed_slice_with_attrs`], except the
893    /// `dma_attrs` is 0 by default.
894    #[inline]
895    pub fn zeroed_slice(
896        dev: &device::Device<Bound>,
897        len: usize,
898        gfp_flags: kernel::alloc::Flags,
899    ) -> Result<Coherent<[T]>> {
900        Self::zeroed_slice_with_attrs(dev, len, gfp_flags, Attrs(0))
901    }
902
903    /// Allocates a region of coherent memory of the same size as `data` and initializes it with a
904    /// copy of its contents.
905    ///
906    /// # Examples
907    ///
908    /// ```
909    /// # use kernel::device::{Bound, Device};
910    /// use kernel::dma::{
911    ///     attrs::*,
912    ///     Coherent
913    /// };
914    ///
915    /// # fn test(dev: &Device<Bound>) -> Result {
916    /// let data = [0u8, 1u8, 2u8, 3u8];
917    /// // `c` has the same content as `data`.
918    /// let c: Coherent<[u8]> =
919    ///     Coherent::from_slice_with_attrs(dev, &data, GFP_KERNEL, DMA_ATTR_NO_WARN)?;
920    ///
921    /// # Ok::<(), Error>(()) }
922    /// ```
923    #[inline]
924    pub fn from_slice_with_attrs(
925        dev: &device::Device<Bound>,
926        data: &[T],
927        gfp_flags: kernel::alloc::Flags,
928        dma_attrs: Attrs,
929    ) -> Result<Coherent<[T]>>
930    where
931        T: Copy,
932    {
933        CoherentBox::from_slice_with_attrs(dev, data, gfp_flags, dma_attrs).map(Into::into)
934    }
935
936    /// Performs the same functionality as [`Coherent::from_slice_with_attrs`], except the
937    /// `dma_attrs` is 0 by default.
938    #[inline]
939    pub fn from_slice(
940        dev: &device::Device<Bound>,
941        data: &[T],
942        gfp_flags: kernel::alloc::Flags,
943    ) -> Result<Coherent<[T]>>
944    where
945        T: Copy,
946    {
947        Self::from_slice_with_attrs(dev, data, gfp_flags, Attrs(0))
948    }
949}
950
951impl<T> Coherent<[T]> {
952    /// Returns the number of elements `T` in this allocation.
953    ///
954    /// Note that this is not the size of the allocation in bytes, which is provided by
955    /// [`Self::size`].
956    #[inline]
957    #[expect(clippy::len_without_is_empty, reason = "Coherent slice is never empty")]
958    pub fn len(&self) -> usize {
959        self.cpu_addr.len()
960    }
961}
962
963/// Note that the device configured to do DMA must be halted before this object is dropped.
964impl<T: KnownSize + ?Sized> Drop for Coherent<T> {
965    fn drop(&mut self) {
966        let size = T::size(self.cpu_addr.as_ptr());
967        // SAFETY: Device pointer is guaranteed as valid by the type invariant on `Device`.
968        // The cpu address, and the dma handle are valid due to the type invariants on
969        // `Coherent`.
970        unsafe {
971            bindings::dma_free_attrs(
972                self.dev.as_raw(),
973                size,
974                self.cpu_addr.as_ptr().cast(),
975                self.dma_handle,
976                self.dma_attrs.as_raw(),
977            )
978        }
979    }
980}
981
982// SAFETY: It is safe to send a `Coherent` to another thread if `T`
983// can be sent to another thread.
984unsafe impl<T: KnownSize + Send + ?Sized> Send for Coherent<T> {}
985
986// SAFETY: Sharing `&Coherent` across threads is safe if `T` is `Sync`, because all
987// methods that access the buffer contents (`field_read`, `field_write`, `as_slice`,
988// `as_slice_mut`) are `unsafe`, and callers are responsible for ensuring no data races occur.
989// The safe methods only return metadata or raw pointers whose use requires `unsafe`.
990unsafe impl<T: KnownSize + ?Sized + AsBytes + FromBytes + Sync> Sync for Coherent<T> {}
991
992impl<T: KnownSize + AsBytes + ?Sized> debugfs::BinaryWriter for Coherent<T> {
993    fn write_to_slice(
994        &self,
995        writer: &mut UserSliceWriter,
996        offset: &mut file::Offset,
997    ) -> Result<usize> {
998        if offset.is_negative() {
999            return Err(EINVAL);
1000        }
1001
1002        // If the offset is too large for a usize (e.g. on 32-bit platforms),
1003        // then consider that as past EOF and just return 0 bytes.
1004        let Ok(offset_val) = usize::try_from(*offset) else {
1005            return Ok(0);
1006        };
1007
1008        let count = self.size().saturating_sub(offset_val).min(writer.len());
1009
1010        writer.write_dma(self, offset_val, count)?;
1011
1012        *offset += count as i64;
1013        Ok(count)
1014    }
1015}
1016
1017/// An opaque DMA allocation without a kernel virtual mapping.
1018///
1019/// Unlike [`Coherent`], a `CoherentHandle` does not provide CPU access to the allocated memory.
1020/// The allocation is always performed with `DMA_ATTR_NO_KERNEL_MAPPING`, meaning no kernel
1021/// virtual mapping is created for the buffer. The value returned by the C API as the CPU
1022/// address is an opaque handle used only to free the allocation.
1023///
1024/// This is useful for buffers that are only ever accessed by hardware.
1025///
1026/// # Invariants
1027///
1028/// - `cpu_handle` holds the opaque handle returned by `dma_alloc_attrs` with
1029///   `DMA_ATTR_NO_KERNEL_MAPPING` set, and is only valid for passing back to `dma_free_attrs`.
1030/// - `dma_handle` is the corresponding bus address for device DMA.
1031/// - `size` is the allocation size in bytes as passed to `dma_alloc_attrs`.
1032/// - `dma_attrs` contains the attributes used for the allocation, always including
1033///   `DMA_ATTR_NO_KERNEL_MAPPING`.
1034pub struct CoherentHandle {
1035    dev: ARef<device::Device>,
1036    dma_handle: DmaAddress,
1037    cpu_handle: NonNull<c_void>,
1038    size: usize,
1039    dma_attrs: Attrs,
1040}
1041
1042impl CoherentHandle {
1043    /// Allocates `size` bytes of coherent DMA memory without creating a kernel virtual mapping.
1044    ///
1045    /// Additional DMA attributes may be passed via `dma_attrs`; `DMA_ATTR_NO_KERNEL_MAPPING` is
1046    /// always set implicitly.
1047    ///
1048    /// Returns `EINVAL` if `size` is zero, `ENOMEM` if the allocation fails.
1049    pub fn alloc_with_attrs(
1050        dev: &device::Device<Bound>,
1051        size: usize,
1052        gfp_flags: kernel::alloc::Flags,
1053        dma_attrs: Attrs,
1054    ) -> Result<Self> {
1055        if size == 0 {
1056            return Err(EINVAL);
1057        }
1058
1059        let dma_attrs = dma_attrs | Attrs(bindings::DMA_ATTR_NO_KERNEL_MAPPING);
1060        let mut dma_handle = 0;
1061        // SAFETY: `dev.as_raw()` is valid by the type invariant on `device::Device`.
1062        let cpu_handle = unsafe {
1063            bindings::dma_alloc_attrs(
1064                dev.as_raw(),
1065                size,
1066                &mut dma_handle,
1067                gfp_flags.as_raw(),
1068                dma_attrs.as_raw(),
1069            )
1070        };
1071
1072        let cpu_handle = NonNull::new(cpu_handle).ok_or(ENOMEM)?;
1073
1074        // INVARIANT: `cpu_handle` is the opaque handle from a successful `dma_alloc_attrs` call
1075        // with `DMA_ATTR_NO_KERNEL_MAPPING`, `dma_handle` is the corresponding DMA address,
1076        // and we hold a refcounted reference to the device.
1077        Ok(Self {
1078            dev: dev.into(),
1079            dma_handle,
1080            cpu_handle,
1081            size,
1082            dma_attrs,
1083        })
1084    }
1085
1086    /// Allocates `size` bytes of coherent DMA memory without creating a kernel virtual mapping.
1087    #[inline]
1088    pub fn alloc(
1089        dev: &device::Device<Bound>,
1090        size: usize,
1091        gfp_flags: kernel::alloc::Flags,
1092    ) -> Result<Self> {
1093        Self::alloc_with_attrs(dev, size, gfp_flags, Attrs(0))
1094    }
1095
1096    /// Returns the DMA handle for this allocation.
1097    ///
1098    /// This address can be programmed into device hardware for DMA access.
1099    #[inline]
1100    pub fn dma_handle(&self) -> DmaAddress {
1101        self.dma_handle
1102    }
1103
1104    /// Returns the size in bytes of this allocation.
1105    #[inline]
1106    pub fn size(&self) -> usize {
1107        self.size
1108    }
1109}
1110
1111impl Drop for CoherentHandle {
1112    fn drop(&mut self) {
1113        // SAFETY: All values are valid by the type invariants on `CoherentHandle`.
1114        // `cpu_handle` is the opaque handle from `dma_alloc_attrs` and is passed back unchanged.
1115        unsafe {
1116            bindings::dma_free_attrs(
1117                self.dev.as_raw(),
1118                self.size,
1119                self.cpu_handle.as_ptr(),
1120                self.dma_handle,
1121                self.dma_attrs.as_raw(),
1122            )
1123        }
1124    }
1125}
1126
1127// SAFETY: `CoherentHandle` only holds a device reference, a DMA handle, an opaque CPU handle,
1128// and a size. None of these are tied to a specific thread.
1129unsafe impl Send for CoherentHandle {}
1130
1131// SAFETY: `CoherentHandle` provides no CPU access to the underlying allocation. The only
1132// operations on `&CoherentHandle` are reading the DMA handle and size, both of which are
1133// plain `Copy` values.
1134unsafe impl Sync for CoherentHandle {}
1135
1136/// Reads a field of an item from an allocated region of structs.
1137///
1138/// The syntax is of the form `kernel::dma_read!(dma, proj)` where `dma` is an expression evaluating
1139/// to a [`Coherent`] and `proj` is a [projection specification](kernel::ptr::project!).
1140///
1141/// # Examples
1142///
1143/// ```
1144/// use kernel::device::Device;
1145/// use kernel::dma::{attrs::*, Coherent};
1146///
1147/// struct MyStruct { field: u32, }
1148///
1149/// // SAFETY: All bit patterns are acceptable values for `MyStruct`.
1150/// unsafe impl kernel::transmute::FromBytes for MyStruct{};
1151/// // SAFETY: Instances of `MyStruct` have no uninitialized portions.
1152/// unsafe impl kernel::transmute::AsBytes for MyStruct{};
1153///
1154/// # fn test(alloc: &kernel::dma::Coherent<[MyStruct]>) -> Result {
1155/// let whole = kernel::dma_read!(alloc, [2]?);
1156/// let field = kernel::dma_read!(alloc, [1]?.field);
1157/// # Ok::<(), Error>(()) }
1158/// ```
1159#[macro_export]
1160macro_rules! dma_read {
1161    ($dma:expr, $($proj:tt)*) => {{
1162        let dma = &$dma;
1163        let ptr = $crate::ptr::project!(
1164            $crate::dma::Coherent::as_ptr(dma), $($proj)*
1165        );
1166        // SAFETY: The pointer created by the projection is within the DMA region.
1167        unsafe { $crate::dma::Coherent::field_read(dma, ptr) }
1168    }};
1169}
1170
1171/// Writes to a field of an item from an allocated region of structs.
1172///
1173/// The syntax is of the form `kernel::dma_write!(dma, proj, val)` where `dma` is an expression
1174/// evaluating to a [`Coherent`], `proj` is a
1175/// [projection specification](kernel::ptr::project!), and `val` is the value to be written to the
1176/// projected location.
1177///
1178/// # Examples
1179///
1180/// ```
1181/// use kernel::device::Device;
1182/// use kernel::dma::{attrs::*, Coherent};
1183///
1184/// struct MyStruct { member: u32, }
1185///
1186/// // SAFETY: All bit patterns are acceptable values for `MyStruct`.
1187/// unsafe impl kernel::transmute::FromBytes for MyStruct{};
1188/// // SAFETY: Instances of `MyStruct` have no uninitialized portions.
1189/// unsafe impl kernel::transmute::AsBytes for MyStruct{};
1190///
1191/// # fn test(alloc: &kernel::dma::Coherent<[MyStruct]>) -> Result {
1192/// kernel::dma_write!(alloc, [2]?.member, 0xf);
1193/// kernel::dma_write!(alloc, [1]?, MyStruct { member: 0xf });
1194/// # Ok::<(), Error>(()) }
1195/// ```
1196#[macro_export]
1197macro_rules! dma_write {
1198    (@parse [$dma:expr] [$($proj:tt)*] [, $val:expr]) => {{
1199        let dma = &$dma;
1200        let ptr = $crate::ptr::project!(
1201            mut $crate::dma::Coherent::as_mut_ptr(dma), $($proj)*
1202        );
1203        let val = $val;
1204        // SAFETY: The pointer created by the projection is within the DMA region.
1205        unsafe { $crate::dma::Coherent::field_write(dma, ptr, val) }
1206    }};
1207    (@parse [$dma:expr] [$($proj:tt)*] [.$field:tt $($rest:tt)*]) => {
1208        $crate::dma_write!(@parse [$dma] [$($proj)* .$field] [$($rest)*])
1209    };
1210    (@parse [$dma:expr] [$($proj:tt)*] [[$index:expr]? $($rest:tt)*]) => {
1211        $crate::dma_write!(@parse [$dma] [$($proj)* [$index]?] [$($rest)*])
1212    };
1213    (@parse [$dma:expr] [$($proj:tt)*] [[$index:expr] $($rest:tt)*]) => {
1214        $crate::dma_write!(@parse [$dma] [$($proj)* [$index]] [$($rest)*])
1215    };
1216    ($dma:expr, $($rest:tt)*) => {
1217        $crate::dma_write!(@parse [$dma] [] [$($rest)*])
1218    };
1219}