xref: /linux/rust/kernel/dma.rs (revision 38f7e5450ebfc6f2e046a249a3f629ea7bec8c31)
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     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 };
26 use 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.
42 pub 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)
50 pub 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)]
131 pub struct DmaMask(u64);
132 
133 impl 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)]
224 pub struct Attrs(u32);
225 
226 impl 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 
238 impl 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 
245 impl 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 
252 impl 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.
260 pub 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     /// Lets the platform to avoid creating a kernel virtual mapping for the allocated buffer.
271     pub const DMA_ATTR_NO_KERNEL_MAPPING: Attrs = Attrs(bindings::DMA_ATTR_NO_KERNEL_MAPPING);
272 
273     /// Allows platform code to skip synchronization of the CPU cache for the given buffer assuming
274     /// that it has been already transferred to 'device' domain.
275     pub const DMA_ATTR_SKIP_CPU_SYNC: Attrs = Attrs(bindings::DMA_ATTR_SKIP_CPU_SYNC);
276 
277     /// Forces contiguous allocation of the buffer in physical memory.
278     pub const DMA_ATTR_FORCE_CONTIGUOUS: Attrs = Attrs(bindings::DMA_ATTR_FORCE_CONTIGUOUS);
279 
280     /// Hints DMA-mapping subsystem that it's probably not worth the time to try
281     /// to allocate memory to in a way that gives better TLB efficiency.
282     pub const DMA_ATTR_ALLOC_SINGLE_PAGES: Attrs = Attrs(bindings::DMA_ATTR_ALLOC_SINGLE_PAGES);
283 
284     /// This tells the DMA-mapping subsystem to suppress allocation failure reports (similarly to
285     /// `__GFP_NOWARN`).
286     pub const DMA_ATTR_NO_WARN: Attrs = Attrs(bindings::DMA_ATTR_NO_WARN);
287 
288     /// Indicates that the buffer is fully accessible at an elevated privilege level (and
289     /// ideally inaccessible or at least read-only at lesser-privileged levels).
290     pub const DMA_ATTR_PRIVILEGED: Attrs = Attrs(bindings::DMA_ATTR_PRIVILEGED);
291 
292     /// Indicates that the buffer is MMIO memory.
293     pub const DMA_ATTR_MMIO: Attrs = Attrs(bindings::DMA_ATTR_MMIO);
294 }
295 
296 /// DMA data direction.
297 ///
298 /// Corresponds to the C [`enum dma_data_direction`].
299 ///
300 /// [`enum dma_data_direction`]: srctree/include/linux/dma-direction.h
301 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
302 #[repr(u32)]
303 pub enum DataDirection {
304     /// The DMA mapping is for bidirectional data transfer.
305     ///
306     /// This is used when the buffer can be both read from and written to by the device.
307     /// The cache for the corresponding memory region is both flushed and invalidated.
308     Bidirectional = Self::const_cast(bindings::dma_data_direction_DMA_BIDIRECTIONAL),
309 
310     /// The DMA mapping is for data transfer from memory to the device (write).
311     ///
312     /// The CPU has prepared data in the buffer, and the device will read it.
313     /// The cache for the corresponding memory region is flushed before device access.
314     ToDevice = Self::const_cast(bindings::dma_data_direction_DMA_TO_DEVICE),
315 
316     /// The DMA mapping is for data transfer from the device to memory (read).
317     ///
318     /// The device will write data into the buffer for the CPU to read.
319     /// The cache for the corresponding memory region is invalidated before CPU access.
320     FromDevice = Self::const_cast(bindings::dma_data_direction_DMA_FROM_DEVICE),
321 
322     /// The DMA mapping is not for data transfer.
323     ///
324     /// This is primarily for debugging purposes. With this direction, the DMA mapping API
325     /// will not perform any cache coherency operations.
326     None = Self::const_cast(bindings::dma_data_direction_DMA_NONE),
327 }
328 
329 impl DataDirection {
330     /// Casts the bindgen-generated enum type to a `u32` at compile time.
331     ///
332     /// This function will cause a compile-time error if the underlying value of the
333     /// C enum is out of bounds for `u32`.
334     const fn const_cast(val: bindings::dma_data_direction) -> u32 {
335         // CAST: The C standard allows compilers to choose different integer types for enums.
336         // To safely check the value, we cast it to a wide signed integer type (`i128`)
337         // which can hold any standard C integer enum type without truncation.
338         let wide_val = val as i128;
339 
340         // Check if the value is outside the valid range for the target type `u32`.
341         // CAST: `u32::MAX` is cast to `i128` to match the type of `wide_val` for the comparison.
342         if wide_val < 0 || wide_val > u32::MAX as i128 {
343             // Trigger a compile-time error in a const context.
344             build_error!("C enum value is out of bounds for the target type `u32`.");
345         }
346 
347         // CAST: This cast is valid because the check above guarantees that `wide_val`
348         // is within the representable range of `u32`.
349         wide_val as u32
350     }
351 }
352 
353 impl From<DataDirection> for bindings::dma_data_direction {
354     /// Returns the raw representation of [`enum dma_data_direction`].
355     fn from(direction: DataDirection) -> Self {
356         // CAST: `direction as u32` gets the underlying representation of our `#[repr(u32)]` enum.
357         // The subsequent cast to `Self` (the bindgen type) assumes the C enum is compatible
358         // with the enum variants of `DataDirection`, which is a valid assumption given our
359         // compile-time checks.
360         direction as u32 as Self
361     }
362 }
363 
364 /// CPU-owned DMA allocation that can be converted into a device-shared [`Coherent`] object.
365 ///
366 /// Unlike [`Coherent`], a [`CoherentBox`] is guaranteed to be fully owned by the CPU -- its DMA
367 /// address is not exposed and it cannot be accessed by a device. This means it can safely be used
368 /// like a normal boxed allocation (e.g. direct reads, writes, and mutable slices are all safe).
369 ///
370 /// A typical use is to allocate a [`CoherentBox`], populate it with normal CPU access, and then
371 /// convert it into a [`Coherent`] object to share it with the device.
372 ///
373 /// # Examples
374 ///
375 /// `CoherentBox<T>`:
376 ///
377 /// ```
378 /// # use kernel::device::{
379 /// #     Bound,
380 /// #     Device,
381 /// # };
382 /// use kernel::dma::{attrs::*,
383 ///     Coherent,
384 ///     CoherentBox,
385 /// };
386 ///
387 /// # fn test(dev: &Device<Bound>) -> Result {
388 /// let mut dmem: CoherentBox<u64> = CoherentBox::zeroed(dev, GFP_KERNEL)?;
389 /// *dmem = 42;
390 /// let dmem: Coherent<u64> = dmem.into();
391 /// # Ok::<(), Error>(()) }
392 /// ```
393 ///
394 /// `CoherentBox<[T]>`:
395 ///
396 ///
397 /// ```
398 /// # use kernel::device::{
399 /// #     Bound,
400 /// #     Device,
401 /// # };
402 /// use kernel::dma::{attrs::*,
403 ///     Coherent,
404 ///     CoherentBox,
405 /// };
406 ///
407 /// # fn test(dev: &Device<Bound>) -> Result {
408 /// let mut dmem: CoherentBox<[u64]> = CoherentBox::zeroed_slice(dev, 4, GFP_KERNEL)?;
409 /// dmem.fill(42);
410 /// let dmem: Coherent<[u64]> = dmem.into();
411 /// # Ok::<(), Error>(()) }
412 /// ```
413 pub struct CoherentBox<T: KnownSize + ?Sized>(Coherent<T>);
414 
415 impl<T: AsBytes + FromBytes> CoherentBox<[T]> {
416     /// [`CoherentBox`] variant of [`Coherent::zeroed_slice_with_attrs`].
417     #[inline]
418     pub fn zeroed_slice_with_attrs(
419         dev: &device::Device<Bound>,
420         count: usize,
421         gfp_flags: kernel::alloc::Flags,
422         dma_attrs: Attrs,
423     ) -> Result<Self> {
424         Coherent::zeroed_slice_with_attrs(dev, count, gfp_flags, dma_attrs).map(Self)
425     }
426 
427     /// Same as [CoherentBox::zeroed_slice_with_attrs], but with `dma::Attrs(0)`.
428     #[inline]
429     pub fn zeroed_slice(
430         dev: &device::Device<Bound>,
431         count: usize,
432         gfp_flags: kernel::alloc::Flags,
433     ) -> Result<Self> {
434         Self::zeroed_slice_with_attrs(dev, count, gfp_flags, Attrs(0))
435     }
436 
437     /// Initializes the element at `i` using the given initializer.
438     ///
439     /// Returns `EINVAL` if `i` is out of bounds.
440     pub fn init_at<E>(&mut self, i: usize, init: impl Init<T, E>) -> Result
441     where
442         Error: From<E>,
443     {
444         if i >= self.0.len() {
445             return Err(EINVAL);
446         }
447 
448         let ptr = &raw mut self[i];
449 
450         // SAFETY:
451         // - `ptr` is valid, properly aligned, and within this allocation.
452         // - `T: AsBytes + FromBytes` guarantees all bit patterns are valid, so partial writes on
453         //   error cannot leave the element in an invalid state.
454         // - The DMA address has not been exposed yet, so there is no concurrent device access.
455         unsafe { init.__init(ptr)? };
456 
457         Ok(())
458     }
459 }
460 
461 impl<T: AsBytes + FromBytes> CoherentBox<T> {
462     /// Same as [`CoherentBox::zeroed_slice_with_attrs`], but for a single element.
463     #[inline]
464     pub fn zeroed_with_attrs(
465         dev: &device::Device<Bound>,
466         gfp_flags: kernel::alloc::Flags,
467         dma_attrs: Attrs,
468     ) -> Result<Self> {
469         Coherent::zeroed_with_attrs(dev, gfp_flags, dma_attrs).map(Self)
470     }
471 
472     /// Same as [`CoherentBox::zeroed_slice`], but for a single element.
473     #[inline]
474     pub fn zeroed(dev: &device::Device<Bound>, gfp_flags: kernel::alloc::Flags) -> Result<Self> {
475         Self::zeroed_with_attrs(dev, gfp_flags, Attrs(0))
476     }
477 }
478 
479 impl<T: KnownSize + ?Sized> Deref for CoherentBox<T> {
480     type Target = T;
481 
482     #[inline]
483     fn deref(&self) -> &Self::Target {
484         // SAFETY:
485         // - We have not exposed the DMA address yet, so there can't be any concurrent access by a
486         //   device.
487         // - We have exclusive access to `self.0`.
488         unsafe { self.0.as_ref() }
489     }
490 }
491 
492 impl<T: AsBytes + FromBytes + KnownSize + ?Sized> DerefMut for CoherentBox<T> {
493     #[inline]
494     fn deref_mut(&mut self) -> &mut Self::Target {
495         // SAFETY:
496         // - We have not exposed the DMA address yet, so there can't be any concurrent access by a
497         //   device.
498         // - We have exclusive access to `self.0`.
499         unsafe { self.0.as_mut() }
500     }
501 }
502 
503 impl<T: AsBytes + FromBytes + KnownSize + ?Sized> From<CoherentBox<T>> for Coherent<T> {
504     #[inline]
505     fn from(value: CoherentBox<T>) -> Self {
506         value.0
507     }
508 }
509 
510 /// An abstraction of the `dma_alloc_coherent` API.
511 ///
512 /// This is an abstraction around the `dma_alloc_coherent` API which is used to allocate and map
513 /// large coherent DMA regions.
514 ///
515 /// A [`Coherent`] instance contains a pointer to the allocated region (in the
516 /// processor's virtual address space) and the device address which can be given to the device
517 /// as the DMA address base of the region. The region is released once [`Coherent`]
518 /// is dropped.
519 ///
520 /// # Invariants
521 ///
522 /// - For the lifetime of an instance of [`Coherent`], the `cpu_addr` is a valid pointer
523 ///   to an allocated region of coherent memory and `dma_handle` is the DMA address base of the
524 ///   region.
525 /// - The size in bytes of the allocation is equal to size information via pointer.
526 // TODO
527 //
528 // DMA allocations potentially carry device resources (e.g.IOMMU mappings), hence for soundness
529 // reasons DMA allocation would need to be embedded in a `Devres` container, in order to ensure
530 // that device resources can never survive device unbind.
531 //
532 // However, it is neither desirable nor necessary to protect the allocated memory of the DMA
533 // allocation from surviving device unbind; it would require RCU read side critical sections to
534 // access the memory, which may require subsequent unnecessary copies.
535 //
536 // Hence, find a way to revoke the device resources of a `Coherent`, but not the
537 // entire `Coherent` including the allocated memory itself.
538 pub struct Coherent<T: KnownSize + ?Sized> {
539     dev: ARef<device::Device>,
540     dma_handle: DmaAddress,
541     cpu_addr: NonNull<T>,
542     dma_attrs: Attrs,
543 }
544 
545 impl<T: KnownSize + ?Sized> Coherent<T> {
546     /// Returns the size in bytes of this allocation.
547     #[inline]
548     pub fn size(&self) -> usize {
549         T::size(self.cpu_addr.as_ptr())
550     }
551 
552     /// Returns the raw pointer to the allocated region in the CPU's virtual address space.
553     #[inline]
554     pub fn as_ptr(&self) -> *const T {
555         self.cpu_addr.as_ptr()
556     }
557 
558     /// Returns the raw pointer to the allocated region in the CPU's virtual address space as
559     /// a mutable pointer.
560     #[inline]
561     pub fn as_mut_ptr(&self) -> *mut T {
562         self.cpu_addr.as_ptr()
563     }
564 
565     /// Returns a DMA handle which may be given to the device as the DMA address base of
566     /// the region.
567     #[inline]
568     pub fn dma_handle(&self) -> DmaAddress {
569         self.dma_handle
570     }
571 
572     /// Returns a reference to the data in the region.
573     ///
574     /// # Safety
575     ///
576     /// * Callers must ensure that the device does not read/write to/from memory while the returned
577     ///   slice is live.
578     /// * Callers must ensure that this call does not race with a write to the same region while
579     ///   the returned slice is live.
580     #[inline]
581     pub unsafe fn as_ref(&self) -> &T {
582         // SAFETY: per safety requirement.
583         unsafe { &*self.as_ptr() }
584     }
585 
586     /// Returns a mutable reference to the data in the region.
587     ///
588     /// # Safety
589     ///
590     /// * Callers must ensure that the device does not read/write to/from memory while the returned
591     ///   slice is live.
592     /// * Callers must ensure that this call does not race with a read or write to the same region
593     ///   while the returned slice is live.
594     #[expect(clippy::mut_from_ref, reason = "unsafe to use API")]
595     #[inline]
596     pub unsafe fn as_mut(&self) -> &mut T {
597         // SAFETY: per safety requirement.
598         unsafe { &mut *self.as_mut_ptr() }
599     }
600 
601     /// Reads the value of `field` and ensures that its type is [`FromBytes`].
602     ///
603     /// # Safety
604     ///
605     /// This must be called from the [`dma_read`] macro which ensures that the `field` pointer is
606     /// validated beforehand.
607     ///
608     /// Public but hidden since it should only be used from [`dma_read`] macro.
609     #[doc(hidden)]
610     pub unsafe fn field_read<F: FromBytes>(&self, field: *const F) -> F {
611         // SAFETY:
612         // - By the safety requirements field is valid.
613         // - Using read_volatile() here is not sound as per the usual rules, the usage here is
614         // a special exception with the following notes in place. When dealing with a potential
615         // race from a hardware or code outside kernel (e.g. user-space program), we need that
616         // read on a valid memory is not UB. Currently read_volatile() is used for this, and the
617         // rationale behind is that it should generate the same code as READ_ONCE() which the
618         // kernel already relies on to avoid UB on data races. Note that the usage of
619         // read_volatile() is limited to this particular case, it cannot be used to prevent
620         // the UB caused by racing between two kernel functions nor do they provide atomicity.
621         unsafe { field.read_volatile() }
622     }
623 
624     /// Writes a value to `field` and ensures that its type is [`AsBytes`].
625     ///
626     /// # Safety
627     ///
628     /// This must be called from the [`dma_write`] macro which ensures that the `field` pointer is
629     /// validated beforehand.
630     ///
631     /// Public but hidden since it should only be used from [`dma_write`] macro.
632     #[doc(hidden)]
633     pub unsafe fn field_write<F: AsBytes>(&self, field: *mut F, val: F) {
634         // SAFETY:
635         // - By the safety requirements field is valid.
636         // - Using write_volatile() here is not sound as per the usual rules, the usage here is
637         // a special exception with the following notes in place. When dealing with a potential
638         // race from a hardware or code outside kernel (e.g. user-space program), we need that
639         // write on a valid memory is not UB. Currently write_volatile() is used for this, and the
640         // rationale behind is that it should generate the same code as WRITE_ONCE() which the
641         // kernel already relies on to avoid UB on data races. Note that the usage of
642         // write_volatile() is limited to this particular case, it cannot be used to prevent
643         // the UB caused by racing between two kernel functions nor do they provide atomicity.
644         unsafe { field.write_volatile(val) }
645     }
646 }
647 
648 impl<T: AsBytes + FromBytes> Coherent<T> {
649     /// Allocates a region of `T` of coherent memory.
650     fn alloc_with_attrs(
651         dev: &device::Device<Bound>,
652         gfp_flags: kernel::alloc::Flags,
653         dma_attrs: Attrs,
654     ) -> Result<Self> {
655         const {
656             assert!(
657                 core::mem::size_of::<T>() > 0,
658                 "It doesn't make sense for the allocated type to be a ZST"
659             );
660         }
661 
662         let mut dma_handle = 0;
663         // SAFETY: Device pointer is guaranteed as valid by the type invariant on `Device`.
664         let addr = unsafe {
665             bindings::dma_alloc_attrs(
666                 dev.as_raw(),
667                 core::mem::size_of::<T>(),
668                 &mut dma_handle,
669                 gfp_flags.as_raw(),
670                 dma_attrs.as_raw(),
671             )
672         };
673         let cpu_addr = NonNull::new(addr.cast()).ok_or(ENOMEM)?;
674         // INVARIANT:
675         // - We just successfully allocated a coherent region which is adequately sized for `T`,
676         //   hence the cpu address is valid.
677         // - We also hold a refcounted reference to the device.
678         Ok(Self {
679             dev: dev.into(),
680             dma_handle,
681             cpu_addr,
682             dma_attrs,
683         })
684     }
685 
686     /// Allocates a region of type `T` of coherent memory.
687     ///
688     /// # Examples
689     ///
690     /// ```
691     /// # use kernel::device::{
692     /// #     Bound,
693     /// #     Device,
694     /// # };
695     /// use kernel::dma::{
696     ///     attrs::*,
697     ///     Coherent,
698     /// };
699     ///
700     /// # fn test(dev: &Device<Bound>) -> Result {
701     /// let c: Coherent<[u64; 4]> =
702     ///     Coherent::zeroed_with_attrs(dev, GFP_KERNEL, DMA_ATTR_NO_WARN)?;
703     /// # Ok::<(), Error>(()) }
704     /// ```
705     #[inline]
706     pub fn zeroed_with_attrs(
707         dev: &device::Device<Bound>,
708         gfp_flags: kernel::alloc::Flags,
709         dma_attrs: Attrs,
710     ) -> Result<Self> {
711         Self::alloc_with_attrs(dev, gfp_flags | __GFP_ZERO, dma_attrs)
712     }
713 
714     /// Performs the same functionality as [`Coherent::zeroed_with_attrs`], except the
715     /// `dma_attrs` is 0 by default.
716     #[inline]
717     pub fn zeroed(dev: &device::Device<Bound>, gfp_flags: kernel::alloc::Flags) -> Result<Self> {
718         Self::zeroed_with_attrs(dev, gfp_flags, Attrs(0))
719     }
720 
721     /// Same as [`Coherent::zeroed_with_attrs`], but instead of a zero-initialization the memory is
722     /// initialized with `init`.
723     pub fn init_with_attrs<E>(
724         dev: &device::Device<Bound>,
725         gfp_flags: kernel::alloc::Flags,
726         dma_attrs: Attrs,
727         init: impl Init<T, E>,
728     ) -> Result<Self>
729     where
730         Error: From<E>,
731     {
732         let dmem = Self::alloc_with_attrs(dev, gfp_flags, dma_attrs)?;
733         let ptr = dmem.as_mut_ptr();
734 
735         // SAFETY:
736         // - `ptr` is valid, properly aligned, and points to exclusively owned memory.
737         // - If `__init` fails, `self` is dropped, which safely frees the underlying `Coherent`'s
738         //   DMA memory. `T: AsBytes + FromBytes` ensures there are no complex `Drop` requirements
739         //   we are bypassing.
740         unsafe { init.__init(ptr)? };
741 
742         Ok(dmem)
743     }
744 
745     /// Same as [`Coherent::zeroed`], but instead of a zero-initialization the memory is initialized
746     /// with `init`.
747     #[inline]
748     pub fn init<E>(
749         dev: &device::Device<Bound>,
750         gfp_flags: kernel::alloc::Flags,
751         init: impl Init<T, E>,
752     ) -> Result<Self>
753     where
754         Error: From<E>,
755     {
756         Self::init_with_attrs(dev, gfp_flags, Attrs(0), init)
757     }
758 
759     /// Allocates a region of `[T; len]` of coherent memory.
760     fn alloc_slice_with_attrs(
761         dev: &device::Device<Bound>,
762         len: usize,
763         gfp_flags: kernel::alloc::Flags,
764         dma_attrs: Attrs,
765     ) -> Result<Coherent<[T]>> {
766         const {
767             assert!(
768                 core::mem::size_of::<T>() > 0,
769                 "It doesn't make sense for the allocated type to be a ZST"
770             );
771         }
772 
773         // `dma_alloc_attrs` cannot handle zero-length allocation, bail early.
774         if len == 0 {
775             Err(EINVAL)?;
776         }
777 
778         let size = core::mem::size_of::<T>().checked_mul(len).ok_or(ENOMEM)?;
779         let mut dma_handle = 0;
780         // SAFETY: Device pointer is guaranteed as valid by the type invariant on `Device`.
781         let addr = unsafe {
782             bindings::dma_alloc_attrs(
783                 dev.as_raw(),
784                 size,
785                 &mut dma_handle,
786                 gfp_flags.as_raw(),
787                 dma_attrs.as_raw(),
788             )
789         };
790         let cpu_addr = NonNull::slice_from_raw_parts(NonNull::new(addr.cast()).ok_or(ENOMEM)?, len);
791         // INVARIANT:
792         // - We just successfully allocated a coherent region which is adequately sized for
793         //   `[T; len]`, hence the cpu address is valid.
794         // - We also hold a refcounted reference to the device.
795         Ok(Coherent {
796             dev: dev.into(),
797             dma_handle,
798             cpu_addr,
799             dma_attrs,
800         })
801     }
802 
803     /// Allocates a zeroed region of type `T` of coherent memory.
804     ///
805     /// Unlike `Coherent::<[T; N]>::zeroed_with_attrs`, `Coherent::<T>::zeroed_slices` support
806     /// a runtime length.
807     ///
808     /// # Examples
809     ///
810     /// ```
811     /// # use kernel::device::{
812     /// #     Bound,
813     /// #     Device,
814     /// # };
815     /// use kernel::dma::{
816     ///     attrs::*,
817     ///     Coherent,
818     /// };
819     ///
820     /// # fn test(dev: &Device<Bound>) -> Result {
821     /// let c: Coherent<[u64]> =
822     ///     Coherent::zeroed_slice_with_attrs(dev, 4, GFP_KERNEL, DMA_ATTR_NO_WARN)?;
823     /// # Ok::<(), Error>(()) }
824     /// ```
825     #[inline]
826     pub fn zeroed_slice_with_attrs(
827         dev: &device::Device<Bound>,
828         len: usize,
829         gfp_flags: kernel::alloc::Flags,
830         dma_attrs: Attrs,
831     ) -> Result<Coherent<[T]>> {
832         Coherent::alloc_slice_with_attrs(dev, len, gfp_flags | __GFP_ZERO, dma_attrs)
833     }
834 
835     /// Performs the same functionality as [`Coherent::zeroed_slice_with_attrs`], except the
836     /// `dma_attrs` is 0 by default.
837     #[inline]
838     pub fn zeroed_slice(
839         dev: &device::Device<Bound>,
840         len: usize,
841         gfp_flags: kernel::alloc::Flags,
842     ) -> Result<Coherent<[T]>> {
843         Self::zeroed_slice_with_attrs(dev, len, gfp_flags, Attrs(0))
844     }
845 }
846 
847 impl<T> Coherent<[T]> {
848     /// Returns the number of elements `T` in this allocation.
849     ///
850     /// Note that this is not the size of the allocation in bytes, which is provided by
851     /// [`Self::size`].
852     #[inline]
853     #[expect(clippy::len_without_is_empty, reason = "Coherent slice is never empty")]
854     pub fn len(&self) -> usize {
855         self.cpu_addr.len()
856     }
857 }
858 
859 /// Note that the device configured to do DMA must be halted before this object is dropped.
860 impl<T: KnownSize + ?Sized> Drop for Coherent<T> {
861     fn drop(&mut self) {
862         let size = T::size(self.cpu_addr.as_ptr());
863         // SAFETY: Device pointer is guaranteed as valid by the type invariant on `Device`.
864         // The cpu address, and the dma handle are valid due to the type invariants on
865         // `Coherent`.
866         unsafe {
867             bindings::dma_free_attrs(
868                 self.dev.as_raw(),
869                 size,
870                 self.cpu_addr.as_ptr().cast(),
871                 self.dma_handle,
872                 self.dma_attrs.as_raw(),
873             )
874         }
875     }
876 }
877 
878 // SAFETY: It is safe to send a `Coherent` to another thread if `T`
879 // can be sent to another thread.
880 unsafe impl<T: KnownSize + Send + ?Sized> Send for Coherent<T> {}
881 
882 // SAFETY: Sharing `&Coherent` across threads is safe if `T` is `Sync`, because all
883 // methods that access the buffer contents (`field_read`, `field_write`, `as_slice`,
884 // `as_slice_mut`) are `unsafe`, and callers are responsible for ensuring no data races occur.
885 // The safe methods only return metadata or raw pointers whose use requires `unsafe`.
886 unsafe impl<T: KnownSize + ?Sized + AsBytes + FromBytes + Sync> Sync for Coherent<T> {}
887 
888 impl debugfs::BinaryWriter for Coherent<[u8]> {
889     fn write_to_slice(
890         &self,
891         writer: &mut UserSliceWriter,
892         offset: &mut file::Offset,
893     ) -> Result<usize> {
894         if offset.is_negative() {
895             return Err(EINVAL);
896         }
897 
898         // If the offset is too large for a usize (e.g. on 32-bit platforms),
899         // then consider that as past EOF and just return 0 bytes.
900         let Ok(offset_val) = usize::try_from(*offset) else {
901             return Ok(0);
902         };
903 
904         let count = self.size().saturating_sub(offset_val).min(writer.len());
905 
906         writer.write_dma(self, offset_val, count)?;
907 
908         *offset += count as i64;
909         Ok(count)
910     }
911 }
912 
913 /// Reads a field of an item from an allocated region of structs.
914 ///
915 /// The syntax is of the form `kernel::dma_read!(dma, proj)` where `dma` is an expression evaluating
916 /// to a [`Coherent`] and `proj` is a [projection specification](kernel::ptr::project!).
917 ///
918 /// # Examples
919 ///
920 /// ```
921 /// use kernel::device::Device;
922 /// use kernel::dma::{attrs::*, Coherent};
923 ///
924 /// struct MyStruct { field: u32, }
925 ///
926 /// // SAFETY: All bit patterns are acceptable values for `MyStruct`.
927 /// unsafe impl kernel::transmute::FromBytes for MyStruct{};
928 /// // SAFETY: Instances of `MyStruct` have no uninitialized portions.
929 /// unsafe impl kernel::transmute::AsBytes for MyStruct{};
930 ///
931 /// # fn test(alloc: &kernel::dma::Coherent<[MyStruct]>) -> Result {
932 /// let whole = kernel::dma_read!(alloc, [2]?);
933 /// let field = kernel::dma_read!(alloc, [1]?.field);
934 /// # Ok::<(), Error>(()) }
935 /// ```
936 #[macro_export]
937 macro_rules! dma_read {
938     ($dma:expr, $($proj:tt)*) => {{
939         let dma = &$dma;
940         let ptr = $crate::ptr::project!(
941             $crate::dma::Coherent::as_ptr(dma), $($proj)*
942         );
943         // SAFETY: The pointer created by the projection is within the DMA region.
944         unsafe { $crate::dma::Coherent::field_read(dma, ptr) }
945     }};
946 }
947 
948 /// Writes to a field of an item from an allocated region of structs.
949 ///
950 /// The syntax is of the form `kernel::dma_write!(dma, proj, val)` where `dma` is an expression
951 /// evaluating to a [`Coherent`], `proj` is a
952 /// [projection specification](kernel::ptr::project!), and `val` is the value to be written to the
953 /// projected location.
954 ///
955 /// # Examples
956 ///
957 /// ```
958 /// use kernel::device::Device;
959 /// use kernel::dma::{attrs::*, Coherent};
960 ///
961 /// struct MyStruct { member: u32, }
962 ///
963 /// // SAFETY: All bit patterns are acceptable values for `MyStruct`.
964 /// unsafe impl kernel::transmute::FromBytes for MyStruct{};
965 /// // SAFETY: Instances of `MyStruct` have no uninitialized portions.
966 /// unsafe impl kernel::transmute::AsBytes for MyStruct{};
967 ///
968 /// # fn test(alloc: &kernel::dma::Coherent<[MyStruct]>) -> Result {
969 /// kernel::dma_write!(alloc, [2]?.member, 0xf);
970 /// kernel::dma_write!(alloc, [1]?, MyStruct { member: 0xf });
971 /// # Ok::<(), Error>(()) }
972 /// ```
973 #[macro_export]
974 macro_rules! dma_write {
975     (@parse [$dma:expr] [$($proj:tt)*] [, $val:expr]) => {{
976         let dma = &$dma;
977         let ptr = $crate::ptr::project!(
978             mut $crate::dma::Coherent::as_mut_ptr(dma), $($proj)*
979         );
980         let val = $val;
981         // SAFETY: The pointer created by the projection is within the DMA region.
982         unsafe { $crate::dma::Coherent::field_write(dma, ptr, val) }
983     }};
984     (@parse [$dma:expr] [$($proj:tt)*] [.$field:tt $($rest:tt)*]) => {
985         $crate::dma_write!(@parse [$dma] [$($proj)* .$field] [$($rest)*])
986     };
987     (@parse [$dma:expr] [$($proj:tt)*] [[$index:expr]? $($rest:tt)*]) => {
988         $crate::dma_write!(@parse [$dma] [$($proj)* [$index]?] [$($rest)*])
989     };
990     (@parse [$dma:expr] [$($proj:tt)*] [[$index:expr] $($rest:tt)*]) => {
991         $crate::dma_write!(@parse [$dma] [$($proj)* [$index]] [$($rest)*])
992     };
993     ($dma:expr, $($rest:tt)*) => {
994         $crate::dma_write!(@parse [$dma] [] [$($rest)*])
995     };
996 }
997