xref: /linux/rust/kernel/dma.rs (revision f84ecffa3f745572164c1269f20eec2589d432c9)
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 
7 use crate::{
8     bindings,
9     device::{
10         self,
11         Bound,
12         Core, //
13     },
14     error::to_result,
15     prelude::*,
16     ptr::KnownSize,
17     sync::aref::ARef,
18     transmute::{
19         AsBytes,
20         FromBytes, //
21     }, //
22 };
23 use core::ptr::NonNull;
24 
25 /// DMA address type.
26 ///
27 /// Represents a bus address used for Direct Memory Access (DMA) operations.
28 ///
29 /// This is an alias of the kernel's `dma_addr_t`, which may be `u32` or `u64` depending on
30 /// `CONFIG_ARCH_DMA_ADDR_T_64BIT`.
31 ///
32 /// Note that this may be `u64` even on 32-bit architectures.
33 pub type DmaAddress = bindings::dma_addr_t;
34 
35 /// Trait to be implemented by DMA capable bus devices.
36 ///
37 /// The [`dma::Device`](Device) trait should be implemented by bus specific device representations,
38 /// where the underlying bus is DMA capable, such as:
39 #[cfg_attr(CONFIG_PCI, doc = "* [`pci::Device`](kernel::pci::Device)")]
40 /// * [`platform::Device`](::kernel::platform::Device)
41 pub trait Device: AsRef<device::Device<Core>> {
42     /// Set up the device's DMA streaming addressing capabilities.
43     ///
44     /// This method is usually called once from `probe()` as soon as the device capabilities are
45     /// known.
46     ///
47     /// # Safety
48     ///
49     /// This method must not be called concurrently with any DMA allocation or mapping primitives,
50     /// such as [`Coherent::zeroed`].
51     unsafe fn dma_set_mask(&self, mask: DmaMask) -> Result {
52         // SAFETY:
53         // - By the type invariant of `device::Device`, `self.as_ref().as_raw()` is valid.
54         // - The safety requirement of this function guarantees that there are no concurrent calls
55         //   to DMA allocation and mapping primitives using this mask.
56         to_result(unsafe { bindings::dma_set_mask(self.as_ref().as_raw(), mask.value()) })
57     }
58 
59     /// Set up the device's DMA coherent addressing capabilities.
60     ///
61     /// This method is usually called once from `probe()` as soon as the device capabilities are
62     /// known.
63     ///
64     /// # Safety
65     ///
66     /// This method must not be called concurrently with any DMA allocation or mapping primitives,
67     /// such as [`Coherent::zeroed`].
68     unsafe fn dma_set_coherent_mask(&self, mask: DmaMask) -> Result {
69         // SAFETY:
70         // - By the type invariant of `device::Device`, `self.as_ref().as_raw()` is valid.
71         // - The safety requirement of this function guarantees that there are no concurrent calls
72         //   to DMA allocation and mapping primitives using this mask.
73         to_result(unsafe { bindings::dma_set_coherent_mask(self.as_ref().as_raw(), mask.value()) })
74     }
75 
76     /// Set up the device's DMA addressing capabilities.
77     ///
78     /// This is a combination of [`Device::dma_set_mask`] and [`Device::dma_set_coherent_mask`].
79     ///
80     /// This method is usually called once from `probe()` as soon as the device capabilities are
81     /// known.
82     ///
83     /// # Safety
84     ///
85     /// This method must not be called concurrently with any DMA allocation or mapping primitives,
86     /// such as [`Coherent::zeroed`].
87     unsafe fn dma_set_mask_and_coherent(&self, mask: DmaMask) -> Result {
88         // SAFETY:
89         // - By the type invariant of `device::Device`, `self.as_ref().as_raw()` is valid.
90         // - The safety requirement of this function guarantees that there are no concurrent calls
91         //   to DMA allocation and mapping primitives using this mask.
92         to_result(unsafe {
93             bindings::dma_set_mask_and_coherent(self.as_ref().as_raw(), mask.value())
94         })
95     }
96 
97     /// Set the maximum size of a single DMA segment the device may request.
98     ///
99     /// This method is usually called once from `probe()` as soon as the device capabilities are
100     /// known.
101     ///
102     /// # Safety
103     ///
104     /// This method must not be called concurrently with any DMA allocation or mapping primitives,
105     /// such as [`Coherent::zeroed`].
106     unsafe fn dma_set_max_seg_size(&self, size: u32) {
107         // SAFETY:
108         // - By the type invariant of `device::Device`, `self.as_ref().as_raw()` is valid.
109         // - The safety requirement of this function guarantees that there are no concurrent calls
110         //   to DMA allocation and mapping primitives using this parameter.
111         unsafe { bindings::dma_set_max_seg_size(self.as_ref().as_raw(), size) }
112     }
113 }
114 
115 /// A DMA mask that holds a bitmask with the lowest `n` bits set.
116 ///
117 /// Use [`DmaMask::new`] or [`DmaMask::try_new`] to construct a value. Values
118 /// are guaranteed to never exceed the bit width of `u64`.
119 ///
120 /// This is the Rust equivalent of the C macro `DMA_BIT_MASK()`.
121 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
122 pub struct DmaMask(u64);
123 
124 impl DmaMask {
125     /// Constructs a `DmaMask` with the lowest `n` bits set to `1`.
126     ///
127     /// For `n <= 64`, sets exactly the lowest `n` bits.
128     /// For `n > 64`, results in a build error.
129     ///
130     /// # Examples
131     ///
132     /// ```
133     /// use kernel::dma::DmaMask;
134     ///
135     /// let mask0 = DmaMask::new::<0>();
136     /// assert_eq!(mask0.value(), 0);
137     ///
138     /// let mask1 = DmaMask::new::<1>();
139     /// assert_eq!(mask1.value(), 0b1);
140     ///
141     /// let mask64 = DmaMask::new::<64>();
142     /// assert_eq!(mask64.value(), u64::MAX);
143     ///
144     /// // Build failure.
145     /// // let mask_overflow = DmaMask::new::<100>();
146     /// ```
147     #[inline]
148     pub const fn new<const N: u32>() -> Self {
149         let Ok(mask) = Self::try_new(N) else {
150             build_error!("Invalid DMA Mask.");
151         };
152 
153         mask
154     }
155 
156     /// Constructs a `DmaMask` with the lowest `n` bits set to `1`.
157     ///
158     /// For `n <= 64`, sets exactly the lowest `n` bits.
159     /// For `n > 64`, returns [`EINVAL`].
160     ///
161     /// # Examples
162     ///
163     /// ```
164     /// use kernel::dma::DmaMask;
165     ///
166     /// let mask0 = DmaMask::try_new(0)?;
167     /// assert_eq!(mask0.value(), 0);
168     ///
169     /// let mask1 = DmaMask::try_new(1)?;
170     /// assert_eq!(mask1.value(), 0b1);
171     ///
172     /// let mask64 = DmaMask::try_new(64)?;
173     /// assert_eq!(mask64.value(), u64::MAX);
174     ///
175     /// let mask_overflow = DmaMask::try_new(100);
176     /// assert!(mask_overflow.is_err());
177     /// # Ok::<(), Error>(())
178     /// ```
179     #[inline]
180     pub const fn try_new(n: u32) -> Result<Self> {
181         Ok(Self(match n {
182             0 => 0,
183             1..=64 => u64::MAX >> (64 - n),
184             _ => return Err(EINVAL),
185         }))
186     }
187 
188     /// Returns the underlying `u64` bitmask value.
189     #[inline]
190     pub const fn value(&self) -> u64 {
191         self.0
192     }
193 }
194 
195 /// Possible attributes associated with a DMA mapping.
196 ///
197 /// They can be combined with the operators `|`, `&`, and `!`.
198 ///
199 /// Values can be used from the [`attrs`] module.
200 ///
201 /// # Examples
202 ///
203 /// ```
204 /// # use kernel::device::{Bound, Device};
205 /// use kernel::dma::{attrs::*, Coherent};
206 ///
207 /// # fn test(dev: &Device<Bound>) -> Result {
208 /// let attribs = DMA_ATTR_FORCE_CONTIGUOUS | DMA_ATTR_NO_WARN;
209 /// let c: Coherent<[u64]> =
210 ///     Coherent::zeroed_slice_with_attrs(dev, 4, GFP_KERNEL, attribs)?;
211 /// # Ok::<(), Error>(()) }
212 /// ```
213 #[derive(Clone, Copy, PartialEq)]
214 #[repr(transparent)]
215 pub struct Attrs(u32);
216 
217 impl Attrs {
218     /// Get the raw representation of this attribute.
219     pub(crate) fn as_raw(self) -> crate::ffi::c_ulong {
220         self.0 as crate::ffi::c_ulong
221     }
222 
223     /// Check whether `flags` is contained in `self`.
224     pub fn contains(self, flags: Attrs) -> bool {
225         (self & flags) == flags
226     }
227 }
228 
229 impl core::ops::BitOr for Attrs {
230     type Output = Self;
231     fn bitor(self, rhs: Self) -> Self::Output {
232         Self(self.0 | rhs.0)
233     }
234 }
235 
236 impl core::ops::BitAnd for Attrs {
237     type Output = Self;
238     fn bitand(self, rhs: Self) -> Self::Output {
239         Self(self.0 & rhs.0)
240     }
241 }
242 
243 impl core::ops::Not for Attrs {
244     type Output = Self;
245     fn not(self) -> Self::Output {
246         Self(!self.0)
247     }
248 }
249 
250 /// DMA mapping attributes.
251 pub mod attrs {
252     use super::Attrs;
253 
254     /// Specifies that reads and writes to the mapping may be weakly ordered, that is that reads
255     /// and writes may pass each other.
256     pub const DMA_ATTR_WEAK_ORDERING: Attrs = Attrs(bindings::DMA_ATTR_WEAK_ORDERING);
257 
258     /// Specifies that writes to the mapping may be buffered to improve performance.
259     pub const DMA_ATTR_WRITE_COMBINE: Attrs = Attrs(bindings::DMA_ATTR_WRITE_COMBINE);
260 
261     /// Lets the platform to avoid creating a kernel virtual mapping for the allocated buffer.
262     pub const DMA_ATTR_NO_KERNEL_MAPPING: Attrs = Attrs(bindings::DMA_ATTR_NO_KERNEL_MAPPING);
263 
264     /// Allows platform code to skip synchronization of the CPU cache for the given buffer assuming
265     /// that it has been already transferred to 'device' domain.
266     pub const DMA_ATTR_SKIP_CPU_SYNC: Attrs = Attrs(bindings::DMA_ATTR_SKIP_CPU_SYNC);
267 
268     /// Forces contiguous allocation of the buffer in physical memory.
269     pub const DMA_ATTR_FORCE_CONTIGUOUS: Attrs = Attrs(bindings::DMA_ATTR_FORCE_CONTIGUOUS);
270 
271     /// Hints DMA-mapping subsystem that it's probably not worth the time to try
272     /// to allocate memory to in a way that gives better TLB efficiency.
273     pub const DMA_ATTR_ALLOC_SINGLE_PAGES: Attrs = Attrs(bindings::DMA_ATTR_ALLOC_SINGLE_PAGES);
274 
275     /// This tells the DMA-mapping subsystem to suppress allocation failure reports (similarly to
276     /// `__GFP_NOWARN`).
277     pub const DMA_ATTR_NO_WARN: Attrs = Attrs(bindings::DMA_ATTR_NO_WARN);
278 
279     /// Indicates that the buffer is fully accessible at an elevated privilege level (and
280     /// ideally inaccessible or at least read-only at lesser-privileged levels).
281     pub const DMA_ATTR_PRIVILEGED: Attrs = Attrs(bindings::DMA_ATTR_PRIVILEGED);
282 
283     /// Indicates that the buffer is MMIO memory.
284     pub const DMA_ATTR_MMIO: Attrs = Attrs(bindings::DMA_ATTR_MMIO);
285 }
286 
287 /// DMA data direction.
288 ///
289 /// Corresponds to the C [`enum dma_data_direction`].
290 ///
291 /// [`enum dma_data_direction`]: srctree/include/linux/dma-direction.h
292 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
293 #[repr(u32)]
294 pub enum DataDirection {
295     /// The DMA mapping is for bidirectional data transfer.
296     ///
297     /// This is used when the buffer can be both read from and written to by the device.
298     /// The cache for the corresponding memory region is both flushed and invalidated.
299     Bidirectional = Self::const_cast(bindings::dma_data_direction_DMA_BIDIRECTIONAL),
300 
301     /// The DMA mapping is for data transfer from memory to the device (write).
302     ///
303     /// The CPU has prepared data in the buffer, and the device will read it.
304     /// The cache for the corresponding memory region is flushed before device access.
305     ToDevice = Self::const_cast(bindings::dma_data_direction_DMA_TO_DEVICE),
306 
307     /// The DMA mapping is for data transfer from the device to memory (read).
308     ///
309     /// The device will write data into the buffer for the CPU to read.
310     /// The cache for the corresponding memory region is invalidated before CPU access.
311     FromDevice = Self::const_cast(bindings::dma_data_direction_DMA_FROM_DEVICE),
312 
313     /// The DMA mapping is not for data transfer.
314     ///
315     /// This is primarily for debugging purposes. With this direction, the DMA mapping API
316     /// will not perform any cache coherency operations.
317     None = Self::const_cast(bindings::dma_data_direction_DMA_NONE),
318 }
319 
320 impl DataDirection {
321     /// Casts the bindgen-generated enum type to a `u32` at compile time.
322     ///
323     /// This function will cause a compile-time error if the underlying value of the
324     /// C enum is out of bounds for `u32`.
325     const fn const_cast(val: bindings::dma_data_direction) -> u32 {
326         // CAST: The C standard allows compilers to choose different integer types for enums.
327         // To safely check the value, we cast it to a wide signed integer type (`i128`)
328         // which can hold any standard C integer enum type without truncation.
329         let wide_val = val as i128;
330 
331         // Check if the value is outside the valid range for the target type `u32`.
332         // CAST: `u32::MAX` is cast to `i128` to match the type of `wide_val` for the comparison.
333         if wide_val < 0 || wide_val > u32::MAX as i128 {
334             // Trigger a compile-time error in a const context.
335             build_error!("C enum value is out of bounds for the target type `u32`.");
336         }
337 
338         // CAST: This cast is valid because the check above guarantees that `wide_val`
339         // is within the representable range of `u32`.
340         wide_val as u32
341     }
342 }
343 
344 impl From<DataDirection> for bindings::dma_data_direction {
345     /// Returns the raw representation of [`enum dma_data_direction`].
346     fn from(direction: DataDirection) -> Self {
347         // CAST: `direction as u32` gets the underlying representation of our `#[repr(u32)]` enum.
348         // The subsequent cast to `Self` (the bindgen type) assumes the C enum is compatible
349         // with the enum variants of `DataDirection`, which is a valid assumption given our
350         // compile-time checks.
351         direction as u32 as Self
352     }
353 }
354 
355 /// An abstraction of the `dma_alloc_coherent` API.
356 ///
357 /// This is an abstraction around the `dma_alloc_coherent` API which is used to allocate and map
358 /// large coherent DMA regions.
359 ///
360 /// A [`Coherent`] instance contains a pointer to the allocated region (in the
361 /// processor's virtual address space) and the device address which can be given to the device
362 /// as the DMA address base of the region. The region is released once [`Coherent`]
363 /// is dropped.
364 ///
365 /// # Invariants
366 ///
367 /// - For the lifetime of an instance of [`Coherent`], the `cpu_addr` is a valid pointer
368 ///   to an allocated region of coherent memory and `dma_handle` is the DMA address base of the
369 ///   region.
370 /// - The size in bytes of the allocation is equal to size information via pointer.
371 // TODO
372 //
373 // DMA allocations potentially carry device resources (e.g.IOMMU mappings), hence for soundness
374 // reasons DMA allocation would need to be embedded in a `Devres` container, in order to ensure
375 // that device resources can never survive device unbind.
376 //
377 // However, it is neither desirable nor necessary to protect the allocated memory of the DMA
378 // allocation from surviving device unbind; it would require RCU read side critical sections to
379 // access the memory, which may require subsequent unnecessary copies.
380 //
381 // Hence, find a way to revoke the device resources of a `Coherent`, but not the
382 // entire `Coherent` including the allocated memory itself.
383 pub struct Coherent<T: KnownSize + ?Sized> {
384     dev: ARef<device::Device>,
385     dma_handle: DmaAddress,
386     cpu_addr: NonNull<T>,
387     dma_attrs: Attrs,
388 }
389 
390 impl<T: KnownSize + ?Sized> Coherent<T> {
391     /// Returns the size in bytes of this allocation.
392     #[inline]
393     pub fn size(&self) -> usize {
394         T::size(self.cpu_addr.as_ptr())
395     }
396 
397     /// Returns the raw pointer to the allocated region in the CPU's virtual address space.
398     #[inline]
399     pub fn as_ptr(&self) -> *const T {
400         self.cpu_addr.as_ptr()
401     }
402 
403     /// Returns the raw pointer to the allocated region in the CPU's virtual address space as
404     /// a mutable pointer.
405     #[inline]
406     pub fn as_mut_ptr(&self) -> *mut T {
407         self.cpu_addr.as_ptr()
408     }
409 
410     /// Returns a DMA handle which may be given to the device as the DMA address base of
411     /// the region.
412     #[inline]
413     pub fn dma_handle(&self) -> DmaAddress {
414         self.dma_handle
415     }
416 
417     /// Returns a reference to the data in the region.
418     ///
419     /// # Safety
420     ///
421     /// * Callers must ensure that the device does not read/write to/from memory while the returned
422     ///   slice is live.
423     /// * Callers must ensure that this call does not race with a write to the same region while
424     ///   the returned slice is live.
425     #[inline]
426     pub unsafe fn as_ref(&self) -> &T {
427         // SAFETY: per safety requirement.
428         unsafe { &*self.as_ptr() }
429     }
430 
431     /// Returns a mutable reference to the data in the region.
432     ///
433     /// # Safety
434     ///
435     /// * Callers must ensure that the device does not read/write to/from memory while the returned
436     ///   slice is live.
437     /// * Callers must ensure that this call does not race with a read or write to the same region
438     ///   while the returned slice is live.
439     #[expect(clippy::mut_from_ref, reason = "unsafe to use API")]
440     #[inline]
441     pub unsafe fn as_mut(&self) -> &mut T {
442         // SAFETY: per safety requirement.
443         unsafe { &mut *self.as_mut_ptr() }
444     }
445 
446     /// Reads the value of `field` and ensures that its type is [`FromBytes`].
447     ///
448     /// # Safety
449     ///
450     /// This must be called from the [`dma_read`] macro which ensures that the `field` pointer is
451     /// validated beforehand.
452     ///
453     /// Public but hidden since it should only be used from [`dma_read`] macro.
454     #[doc(hidden)]
455     pub unsafe fn field_read<F: FromBytes>(&self, field: *const F) -> F {
456         // SAFETY:
457         // - By the safety requirements field is valid.
458         // - Using read_volatile() here is not sound as per the usual rules, the usage here is
459         // a special exception with the following notes in place. When dealing with a potential
460         // race from a hardware or code outside kernel (e.g. user-space program), we need that
461         // read on a valid memory is not UB. Currently read_volatile() is used for this, and the
462         // rationale behind is that it should generate the same code as READ_ONCE() which the
463         // kernel already relies on to avoid UB on data races. Note that the usage of
464         // read_volatile() is limited to this particular case, it cannot be used to prevent
465         // the UB caused by racing between two kernel functions nor do they provide atomicity.
466         unsafe { field.read_volatile() }
467     }
468 
469     /// Writes a value to `field` and ensures that its type is [`AsBytes`].
470     ///
471     /// # Safety
472     ///
473     /// This must be called from the [`dma_write`] macro which ensures that the `field` pointer is
474     /// validated beforehand.
475     ///
476     /// Public but hidden since it should only be used from [`dma_write`] macro.
477     #[doc(hidden)]
478     pub unsafe fn field_write<F: AsBytes>(&self, field: *mut F, val: F) {
479         // SAFETY:
480         // - By the safety requirements field is valid.
481         // - Using write_volatile() here is not sound as per the usual rules, the usage here is
482         // a special exception with the following notes in place. When dealing with a potential
483         // race from a hardware or code outside kernel (e.g. user-space program), we need that
484         // write on a valid memory is not UB. Currently write_volatile() is used for this, and the
485         // rationale behind is that it should generate the same code as WRITE_ONCE() which the
486         // kernel already relies on to avoid UB on data races. Note that the usage of
487         // write_volatile() is limited to this particular case, it cannot be used to prevent
488         // the UB caused by racing between two kernel functions nor do they provide atomicity.
489         unsafe { field.write_volatile(val) }
490     }
491 }
492 
493 impl<T: AsBytes + FromBytes> Coherent<T> {
494     /// Allocates a region of `T` of coherent memory.
495     fn alloc_with_attrs(
496         dev: &device::Device<Bound>,
497         gfp_flags: kernel::alloc::Flags,
498         dma_attrs: Attrs,
499     ) -> Result<Self> {
500         const {
501             assert!(
502                 core::mem::size_of::<T>() > 0,
503                 "It doesn't make sense for the allocated type to be a ZST"
504             );
505         }
506 
507         let mut dma_handle = 0;
508         // SAFETY: Device pointer is guaranteed as valid by the type invariant on `Device`.
509         let addr = unsafe {
510             bindings::dma_alloc_attrs(
511                 dev.as_raw(),
512                 core::mem::size_of::<T>(),
513                 &mut dma_handle,
514                 gfp_flags.as_raw(),
515                 dma_attrs.as_raw(),
516             )
517         };
518         let cpu_addr = NonNull::new(addr.cast()).ok_or(ENOMEM)?;
519         // INVARIANT:
520         // - We just successfully allocated a coherent region which is adequately sized for `T`,
521         //   hence the cpu address is valid.
522         // - We also hold a refcounted reference to the device.
523         Ok(Self {
524             dev: dev.into(),
525             dma_handle,
526             cpu_addr,
527             dma_attrs,
528         })
529     }
530 
531     /// Allocates a region of type `T` of coherent memory.
532     ///
533     /// # Examples
534     ///
535     /// ```
536     /// # use kernel::device::{
537     /// #     Bound,
538     /// #     Device,
539     /// # };
540     /// use kernel::dma::{
541     ///     attrs::*,
542     ///     Coherent,
543     /// };
544     ///
545     /// # fn test(dev: &Device<Bound>) -> Result {
546     /// let c: Coherent<[u64; 4]> =
547     ///     Coherent::zeroed_with_attrs(dev, GFP_KERNEL, DMA_ATTR_NO_WARN)?;
548     /// # Ok::<(), Error>(()) }
549     /// ```
550     #[inline]
551     pub fn zeroed_with_attrs(
552         dev: &device::Device<Bound>,
553         gfp_flags: kernel::alloc::Flags,
554         dma_attrs: Attrs,
555     ) -> Result<Self> {
556         Self::alloc_with_attrs(dev, gfp_flags | __GFP_ZERO, dma_attrs)
557     }
558 
559     /// Performs the same functionality as [`Coherent::zeroed_with_attrs`], except the
560     /// `dma_attrs` is 0 by default.
561     #[inline]
562     pub fn zeroed(dev: &device::Device<Bound>, gfp_flags: kernel::alloc::Flags) -> Result<Self> {
563         Self::zeroed_with_attrs(dev, gfp_flags, Attrs(0))
564     }
565 
566     /// Allocates a region of `[T; len]` of coherent memory.
567     fn alloc_slice_with_attrs(
568         dev: &device::Device<Bound>,
569         len: usize,
570         gfp_flags: kernel::alloc::Flags,
571         dma_attrs: Attrs,
572     ) -> Result<Coherent<[T]>> {
573         const {
574             assert!(
575                 core::mem::size_of::<T>() > 0,
576                 "It doesn't make sense for the allocated type to be a ZST"
577             );
578         }
579 
580         // `dma_alloc_attrs` cannot handle zero-length allocation, bail early.
581         if len == 0 {
582             Err(EINVAL)?;
583         }
584 
585         let size = core::mem::size_of::<T>().checked_mul(len).ok_or(ENOMEM)?;
586         let mut dma_handle = 0;
587         // SAFETY: Device pointer is guaranteed as valid by the type invariant on `Device`.
588         let addr = unsafe {
589             bindings::dma_alloc_attrs(
590                 dev.as_raw(),
591                 size,
592                 &mut dma_handle,
593                 gfp_flags.as_raw(),
594                 dma_attrs.as_raw(),
595             )
596         };
597         let cpu_addr = NonNull::slice_from_raw_parts(NonNull::new(addr.cast()).ok_or(ENOMEM)?, len);
598         // INVARIANT:
599         // - We just successfully allocated a coherent region which is adequately sized for
600         //   `[T; len]`, hence the cpu address is valid.
601         // - We also hold a refcounted reference to the device.
602         Ok(Coherent {
603             dev: dev.into(),
604             dma_handle,
605             cpu_addr,
606             dma_attrs,
607         })
608     }
609 
610     /// Allocates a zeroed region of type `T` of coherent memory.
611     ///
612     /// Unlike `Coherent::<[T; N]>::zeroed_with_attrs`, `Coherent::<T>::zeroed_slices` support
613     /// a runtime length.
614     ///
615     /// # Examples
616     ///
617     /// ```
618     /// # use kernel::device::{
619     /// #     Bound,
620     /// #     Device,
621     /// # };
622     /// use kernel::dma::{
623     ///     attrs::*,
624     ///     Coherent,
625     /// };
626     ///
627     /// # fn test(dev: &Device<Bound>) -> Result {
628     /// let c: Coherent<[u64]> =
629     ///     Coherent::zeroed_slice_with_attrs(dev, 4, GFP_KERNEL, DMA_ATTR_NO_WARN)?;
630     /// # Ok::<(), Error>(()) }
631     /// ```
632     #[inline]
633     pub fn zeroed_slice_with_attrs(
634         dev: &device::Device<Bound>,
635         len: usize,
636         gfp_flags: kernel::alloc::Flags,
637         dma_attrs: Attrs,
638     ) -> Result<Coherent<[T]>> {
639         Coherent::alloc_slice_with_attrs(dev, len, gfp_flags | __GFP_ZERO, dma_attrs)
640     }
641 
642     /// Performs the same functionality as [`Coherent::zeroed_slice_with_attrs`], except the
643     /// `dma_attrs` is 0 by default.
644     #[inline]
645     pub fn zeroed_slice(
646         dev: &device::Device<Bound>,
647         len: usize,
648         gfp_flags: kernel::alloc::Flags,
649     ) -> Result<Coherent<[T]>> {
650         Self::zeroed_slice_with_attrs(dev, len, gfp_flags, Attrs(0))
651     }
652 }
653 
654 impl<T> Coherent<[T]> {
655     /// Returns the number of elements `T` in this allocation.
656     ///
657     /// Note that this is not the size of the allocation in bytes, which is provided by
658     /// [`Self::size`].
659     #[inline]
660     #[expect(clippy::len_without_is_empty, reason = "Coherent slice is never empty")]
661     pub fn len(&self) -> usize {
662         self.cpu_addr.len()
663     }
664 }
665 
666 // Type alias for compatibility.
667 #[doc(hidden)]
668 pub type CoherentAllocation<T> = Coherent<[T]>;
669 
670 impl<T: AsBytes + FromBytes> CoherentAllocation<T> {
671     /// Allocates a region of `size_of::<T> * count` of coherent memory.
672     ///
673     /// # Examples
674     ///
675     /// ```
676     /// # use kernel::device::{Bound, Device};
677     /// use kernel::dma::{attrs::*, CoherentAllocation};
678     ///
679     /// # fn test(dev: &Device<Bound>) -> Result {
680     /// let c: CoherentAllocation<u64> =
681     ///     CoherentAllocation::alloc_attrs(dev, 4, GFP_KERNEL, DMA_ATTR_NO_WARN)?;
682     /// # Ok::<(), Error>(()) }
683     /// ```
684     pub fn alloc_attrs(
685         dev: &device::Device<Bound>,
686         count: usize,
687         gfp_flags: kernel::alloc::Flags,
688         dma_attrs: Attrs,
689     ) -> Result<CoherentAllocation<T>> {
690         Coherent::alloc_slice_with_attrs(dev, count, gfp_flags, dma_attrs)
691     }
692 
693     /// Performs the same functionality as [`CoherentAllocation::alloc_attrs`], except the
694     /// `dma_attrs` is 0 by default.
695     pub fn alloc_coherent(
696         dev: &device::Device<Bound>,
697         count: usize,
698         gfp_flags: kernel::alloc::Flags,
699     ) -> Result<CoherentAllocation<T>> {
700         CoherentAllocation::alloc_attrs(dev, count, gfp_flags, Attrs(0))
701     }
702 
703     /// Returns the base address to the allocated region in the CPU's virtual address space.
704     pub fn start_ptr(&self) -> *const T {
705         self.as_ptr().cast()
706     }
707 
708     /// Returns the base address to the allocated region in the CPU's virtual address space as
709     /// a mutable pointer.
710     pub fn start_ptr_mut(&mut self) -> *mut T {
711         self.as_mut_ptr().cast()
712     }
713 
714     /// Returns a DMA handle starting at `offset` (in units of `T`) which may be given to the
715     /// device as the DMA address base of the region.
716     ///
717     /// Returns `EINVAL` if `offset` is not within the bounds of the allocation.
718     pub fn dma_handle_with_offset(&self, offset: usize) -> Result<DmaAddress> {
719         if offset >= self.len() {
720             Err(EINVAL)
721         } else {
722             Ok(self.dma_handle + (offset * core::mem::size_of::<T>()) as DmaAddress)
723         }
724     }
725 
726     /// Common helper to validate a range applied from the allocated region in the CPU's virtual
727     /// address space.
728     fn validate_range(&self, offset: usize, count: usize) -> Result {
729         if offset.checked_add(count).ok_or(EOVERFLOW)? > self.len() {
730             return Err(EINVAL);
731         }
732         Ok(())
733     }
734 
735     /// Returns the data from the region starting from `offset` as a slice.
736     /// `offset` and `count` are in units of `T`, not the number of bytes.
737     ///
738     /// For ringbuffer type of r/w access or use-cases where the pointer to the live data is needed,
739     /// [`CoherentAllocation::start_ptr`] or [`CoherentAllocation::start_ptr_mut`] could be used
740     /// instead.
741     ///
742     /// # Safety
743     ///
744     /// * Callers must ensure that the device does not read/write to/from memory while the returned
745     ///   slice is live.
746     /// * Callers must ensure that this call does not race with a write to the same region while
747     ///   the returned slice is live.
748     pub unsafe fn as_slice(&self, offset: usize, count: usize) -> Result<&[T]> {
749         self.validate_range(offset, count)?;
750         // SAFETY:
751         // - The pointer is valid due to type invariant on `CoherentAllocation`,
752         //   we've just checked that the range and index is within bounds. The immutability of the
753         //   data is also guaranteed by the safety requirements of the function.
754         // - `offset + count` can't overflow since it is smaller than `self.count` and we've checked
755         //   that `self.count` won't overflow early in the constructor.
756         Ok(unsafe { core::slice::from_raw_parts(self.start_ptr().add(offset), count) })
757     }
758 
759     /// Performs the same functionality as [`CoherentAllocation::as_slice`], except that a mutable
760     /// slice is returned.
761     ///
762     /// # Safety
763     ///
764     /// * Callers must ensure that the device does not read/write to/from memory while the returned
765     ///   slice is live.
766     /// * Callers must ensure that this call does not race with a read or write to the same region
767     ///   while the returned slice is live.
768     pub unsafe fn as_slice_mut(&mut self, offset: usize, count: usize) -> Result<&mut [T]> {
769         self.validate_range(offset, count)?;
770         // SAFETY:
771         // - The pointer is valid due to type invariant on `CoherentAllocation`,
772         //   we've just checked that the range and index is within bounds. The immutability of the
773         //   data is also guaranteed by the safety requirements of the function.
774         // - `offset + count` can't overflow since it is smaller than `self.count` and we've checked
775         //   that `self.count` won't overflow early in the constructor.
776         Ok(unsafe { core::slice::from_raw_parts_mut(self.start_ptr_mut().add(offset), count) })
777     }
778 
779     /// Writes data to the region starting from `offset`. `offset` is in units of `T`, not the
780     /// number of bytes.
781     ///
782     /// # Safety
783     ///
784     /// * Callers must ensure that this call does not race with a read or write to the same region
785     ///   that overlaps with this write.
786     ///
787     /// # Examples
788     ///
789     /// ```
790     /// # fn test(alloc: &mut kernel::dma::CoherentAllocation<u8>) -> Result {
791     /// let somedata: [u8; 4] = [0xf; 4];
792     /// let buf: &[u8] = &somedata;
793     /// // SAFETY: There is no concurrent HW operation on the device and no other R/W access to the
794     /// // region.
795     /// unsafe { alloc.write(buf, 0)?; }
796     /// # Ok::<(), Error>(()) }
797     /// ```
798     pub unsafe fn write(&mut self, src: &[T], offset: usize) -> Result {
799         self.validate_range(offset, src.len())?;
800         // SAFETY:
801         // - The pointer is valid due to type invariant on `CoherentAllocation`
802         //   and we've just checked that the range and index is within bounds.
803         // - `offset + count` can't overflow since it is smaller than `self.count` and we've checked
804         //   that `self.count` won't overflow early in the constructor.
805         unsafe {
806             core::ptr::copy_nonoverlapping(
807                 src.as_ptr(),
808                 self.start_ptr_mut().add(offset),
809                 src.len(),
810             )
811         };
812         Ok(())
813     }
814 }
815 
816 /// Note that the device configured to do DMA must be halted before this object is dropped.
817 impl<T: KnownSize + ?Sized> Drop for Coherent<T> {
818     fn drop(&mut self) {
819         let size = T::size(self.cpu_addr.as_ptr());
820         // SAFETY: Device pointer is guaranteed as valid by the type invariant on `Device`.
821         // The cpu address, and the dma handle are valid due to the type invariants on
822         // `Coherent`.
823         unsafe {
824             bindings::dma_free_attrs(
825                 self.dev.as_raw(),
826                 size,
827                 self.cpu_addr.as_ptr().cast(),
828                 self.dma_handle,
829                 self.dma_attrs.as_raw(),
830             )
831         }
832     }
833 }
834 
835 // SAFETY: It is safe to send a `Coherent` to another thread if `T`
836 // can be sent to another thread.
837 unsafe impl<T: KnownSize + Send + ?Sized> Send for Coherent<T> {}
838 
839 /// Reads a field of an item from an allocated region of structs.
840 ///
841 /// The syntax is of the form `kernel::dma_read!(dma, proj)` where `dma` is an expression evaluating
842 /// to a [`Coherent`] and `proj` is a [projection specification](kernel::ptr::project!).
843 ///
844 /// # Examples
845 ///
846 /// ```
847 /// use kernel::device::Device;
848 /// use kernel::dma::{attrs::*, Coherent};
849 ///
850 /// struct MyStruct { field: u32, }
851 ///
852 /// // SAFETY: All bit patterns are acceptable values for `MyStruct`.
853 /// unsafe impl kernel::transmute::FromBytes for MyStruct{};
854 /// // SAFETY: Instances of `MyStruct` have no uninitialized portions.
855 /// unsafe impl kernel::transmute::AsBytes for MyStruct{};
856 ///
857 /// # fn test(alloc: &kernel::dma::Coherent<[MyStruct]>) -> Result {
858 /// let whole = kernel::dma_read!(alloc, [2]?);
859 /// let field = kernel::dma_read!(alloc, [1]?.field);
860 /// # Ok::<(), Error>(()) }
861 /// ```
862 #[macro_export]
863 macro_rules! dma_read {
864     ($dma:expr, $($proj:tt)*) => {{
865         let dma = &$dma;
866         let ptr = $crate::ptr::project!(
867             $crate::dma::Coherent::as_ptr(dma), $($proj)*
868         );
869         // SAFETY: The pointer created by the projection is within the DMA region.
870         unsafe { $crate::dma::Coherent::field_read(dma, ptr) }
871     }};
872 }
873 
874 /// Writes to a field of an item from an allocated region of structs.
875 ///
876 /// The syntax is of the form `kernel::dma_write!(dma, proj, val)` where `dma` is an expression
877 /// evaluating to a [`Coherent`], `proj` is a
878 /// [projection specification](kernel::ptr::project!), and `val` is the value to be written to the
879 /// projected location.
880 ///
881 /// # Examples
882 ///
883 /// ```
884 /// use kernel::device::Device;
885 /// use kernel::dma::{attrs::*, Coherent};
886 ///
887 /// struct MyStruct { member: u32, }
888 ///
889 /// // SAFETY: All bit patterns are acceptable values for `MyStruct`.
890 /// unsafe impl kernel::transmute::FromBytes for MyStruct{};
891 /// // SAFETY: Instances of `MyStruct` have no uninitialized portions.
892 /// unsafe impl kernel::transmute::AsBytes for MyStruct{};
893 ///
894 /// # fn test(alloc: &kernel::dma::Coherent<[MyStruct]>) -> Result {
895 /// kernel::dma_write!(alloc, [2]?.member, 0xf);
896 /// kernel::dma_write!(alloc, [1]?, MyStruct { member: 0xf });
897 /// # Ok::<(), Error>(()) }
898 /// ```
899 #[macro_export]
900 macro_rules! dma_write {
901     (@parse [$dma:expr] [$($proj:tt)*] [, $val:expr]) => {{
902         let dma = &$dma;
903         let ptr = $crate::ptr::project!(
904             mut $crate::dma::Coherent::as_mut_ptr(dma), $($proj)*
905         );
906         let val = $val;
907         // SAFETY: The pointer created by the projection is within the DMA region.
908         unsafe { $crate::dma::Coherent::field_write(dma, ptr, val) }
909     }};
910     (@parse [$dma:expr] [$($proj:tt)*] [.$field:tt $($rest:tt)*]) => {
911         $crate::dma_write!(@parse [$dma] [$($proj)* .$field] [$($rest)*])
912     };
913     (@parse [$dma:expr] [$($proj:tt)*] [[$index:expr]? $($rest:tt)*]) => {
914         $crate::dma_write!(@parse [$dma] [$($proj)* [$index]?] [$($rest)*])
915     };
916     (@parse [$dma:expr] [$($proj:tt)*] [[$index:expr] $($rest:tt)*]) => {
917         $crate::dma_write!(@parse [$dma] [$($proj)* [$index]] [$($rest)*])
918     };
919     ($dma:expr, $($rest:tt)*) => {
920         $crate::dma_write!(@parse [$dma] [] [$($rest)*])
921     };
922 }
923