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, build_assert, device,
9    device::{Bound, Core},
10    error::{to_result, Result},
11    prelude::*,
12    transmute::{AsBytes, FromBytes},
13    types::ARef,
14};
15
16/// Trait to be implemented by DMA capable bus devices.
17///
18/// The [`dma::Device`](Device) trait should be implemented by bus specific device representations,
19/// where the underlying bus is DMA capable, such as [`pci::Device`](::kernel::pci::Device) or
20/// [`platform::Device`](::kernel::platform::Device).
21pub trait Device: AsRef<device::Device<Core>> {
22    /// Set up the device's DMA streaming addressing capabilities.
23    ///
24    /// This method is usually called once from `probe()` as soon as the device capabilities are
25    /// known.
26    ///
27    /// # Safety
28    ///
29    /// This method must not be called concurrently with any DMA allocation or mapping primitives,
30    /// such as [`CoherentAllocation::alloc_attrs`].
31    unsafe fn dma_set_mask(&self, mask: DmaMask) -> Result {
32        // SAFETY:
33        // - By the type invariant of `device::Device`, `self.as_ref().as_raw()` is valid.
34        // - The safety requirement of this function guarantees that there are no concurrent calls
35        //   to DMA allocation and mapping primitives using this mask.
36        to_result(unsafe { bindings::dma_set_mask(self.as_ref().as_raw(), mask.value()) })
37    }
38
39    /// Set up the device's DMA coherent addressing capabilities.
40    ///
41    /// This method is usually called once from `probe()` as soon as the device capabilities are
42    /// known.
43    ///
44    /// # Safety
45    ///
46    /// This method must not be called concurrently with any DMA allocation or mapping primitives,
47    /// such as [`CoherentAllocation::alloc_attrs`].
48    unsafe fn dma_set_coherent_mask(&self, mask: DmaMask) -> Result {
49        // SAFETY:
50        // - By the type invariant of `device::Device`, `self.as_ref().as_raw()` is valid.
51        // - The safety requirement of this function guarantees that there are no concurrent calls
52        //   to DMA allocation and mapping primitives using this mask.
53        to_result(unsafe { bindings::dma_set_coherent_mask(self.as_ref().as_raw(), mask.value()) })
54    }
55
56    /// Set up the device's DMA addressing capabilities.
57    ///
58    /// This is a combination of [`Device::dma_set_mask`] and [`Device::dma_set_coherent_mask`].
59    ///
60    /// This method is usually called once from `probe()` as soon as the device capabilities are
61    /// known.
62    ///
63    /// # Safety
64    ///
65    /// This method must not be called concurrently with any DMA allocation or mapping primitives,
66    /// such as [`CoherentAllocation::alloc_attrs`].
67    unsafe fn dma_set_mask_and_coherent(&self, mask: DmaMask) -> Result {
68        // SAFETY:
69        // - By the type invariant of `device::Device`, `self.as_ref().as_raw()` is valid.
70        // - The safety requirement of this function guarantees that there are no concurrent calls
71        //   to DMA allocation and mapping primitives using this mask.
72        to_result(unsafe {
73            bindings::dma_set_mask_and_coherent(self.as_ref().as_raw(), mask.value())
74        })
75    }
76}
77
78/// A DMA mask that holds a bitmask with the lowest `n` bits set.
79///
80/// Use [`DmaMask::new`] or [`DmaMask::try_new`] to construct a value. Values
81/// are guaranteed to never exceed the bit width of `u64`.
82///
83/// This is the Rust equivalent of the C macro `DMA_BIT_MASK()`.
84#[derive(Debug, Clone, Copy, PartialEq, Eq)]
85pub struct DmaMask(u64);
86
87impl DmaMask {
88    /// Constructs a `DmaMask` with the lowest `n` bits set to `1`.
89    ///
90    /// For `n <= 64`, sets exactly the lowest `n` bits.
91    /// For `n > 64`, results in a build error.
92    ///
93    /// # Examples
94    ///
95    /// ```
96    /// use kernel::dma::DmaMask;
97    ///
98    /// let mask0 = DmaMask::new::<0>();
99    /// assert_eq!(mask0.value(), 0);
100    ///
101    /// let mask1 = DmaMask::new::<1>();
102    /// assert_eq!(mask1.value(), 0b1);
103    ///
104    /// let mask64 = DmaMask::new::<64>();
105    /// assert_eq!(mask64.value(), u64::MAX);
106    ///
107    /// // Build failure.
108    /// // let mask_overflow = DmaMask::new::<100>();
109    /// ```
110    #[inline]
111    pub const fn new<const N: u32>() -> Self {
112        let Ok(mask) = Self::try_new(N) else {
113            build_error!("Invalid DMA Mask.");
114        };
115
116        mask
117    }
118
119    /// Constructs a `DmaMask` with the lowest `n` bits set to `1`.
120    ///
121    /// For `n <= 64`, sets exactly the lowest `n` bits.
122    /// For `n > 64`, returns [`EINVAL`].
123    ///
124    /// # Examples
125    ///
126    /// ```
127    /// use kernel::dma::DmaMask;
128    ///
129    /// let mask0 = DmaMask::try_new(0)?;
130    /// assert_eq!(mask0.value(), 0);
131    ///
132    /// let mask1 = DmaMask::try_new(1)?;
133    /// assert_eq!(mask1.value(), 0b1);
134    ///
135    /// let mask64 = DmaMask::try_new(64)?;
136    /// assert_eq!(mask64.value(), u64::MAX);
137    ///
138    /// let mask_overflow = DmaMask::try_new(100);
139    /// assert!(mask_overflow.is_err());
140    /// # Ok::<(), Error>(())
141    /// ```
142    #[inline]
143    pub const fn try_new(n: u32) -> Result<Self> {
144        Ok(Self(match n {
145            0 => 0,
146            1..=64 => u64::MAX >> (64 - n),
147            _ => return Err(EINVAL),
148        }))
149    }
150
151    /// Returns the underlying `u64` bitmask value.
152    #[inline]
153    pub const fn value(&self) -> u64 {
154        self.0
155    }
156}
157
158/// Possible attributes associated with a DMA mapping.
159///
160/// They can be combined with the operators `|`, `&`, and `!`.
161///
162/// Values can be used from the [`attrs`] module.
163///
164/// # Examples
165///
166/// ```
167/// # use kernel::device::{Bound, Device};
168/// use kernel::dma::{attrs::*, CoherentAllocation};
169///
170/// # fn test(dev: &Device<Bound>) -> Result {
171/// let attribs = DMA_ATTR_FORCE_CONTIGUOUS | DMA_ATTR_NO_WARN;
172/// let c: CoherentAllocation<u64> =
173///     CoherentAllocation::alloc_attrs(dev, 4, GFP_KERNEL, attribs)?;
174/// # Ok::<(), Error>(()) }
175/// ```
176#[derive(Clone, Copy, PartialEq)]
177#[repr(transparent)]
178pub struct Attrs(u32);
179
180impl Attrs {
181    /// Get the raw representation of this attribute.
182    pub(crate) fn as_raw(self) -> crate::ffi::c_ulong {
183        self.0 as crate::ffi::c_ulong
184    }
185
186    /// Check whether `flags` is contained in `self`.
187    pub fn contains(self, flags: Attrs) -> bool {
188        (self & flags) == flags
189    }
190}
191
192impl core::ops::BitOr for Attrs {
193    type Output = Self;
194    fn bitor(self, rhs: Self) -> Self::Output {
195        Self(self.0 | rhs.0)
196    }
197}
198
199impl core::ops::BitAnd for Attrs {
200    type Output = Self;
201    fn bitand(self, rhs: Self) -> Self::Output {
202        Self(self.0 & rhs.0)
203    }
204}
205
206impl core::ops::Not for Attrs {
207    type Output = Self;
208    fn not(self) -> Self::Output {
209        Self(!self.0)
210    }
211}
212
213/// DMA mapping attributes.
214pub mod attrs {
215    use super::Attrs;
216
217    /// Specifies that reads and writes to the mapping may be weakly ordered, that is that reads
218    /// and writes may pass each other.
219    pub const DMA_ATTR_WEAK_ORDERING: Attrs = Attrs(bindings::DMA_ATTR_WEAK_ORDERING);
220
221    /// Specifies that writes to the mapping may be buffered to improve performance.
222    pub const DMA_ATTR_WRITE_COMBINE: Attrs = Attrs(bindings::DMA_ATTR_WRITE_COMBINE);
223
224    /// Lets the platform to avoid creating a kernel virtual mapping for the allocated buffer.
225    pub const DMA_ATTR_NO_KERNEL_MAPPING: Attrs = Attrs(bindings::DMA_ATTR_NO_KERNEL_MAPPING);
226
227    /// Allows platform code to skip synchronization of the CPU cache for the given buffer assuming
228    /// that it has been already transferred to 'device' domain.
229    pub const DMA_ATTR_SKIP_CPU_SYNC: Attrs = Attrs(bindings::DMA_ATTR_SKIP_CPU_SYNC);
230
231    /// Forces contiguous allocation of the buffer in physical memory.
232    pub const DMA_ATTR_FORCE_CONTIGUOUS: Attrs = Attrs(bindings::DMA_ATTR_FORCE_CONTIGUOUS);
233
234    /// Hints DMA-mapping subsystem that it's probably not worth the time to try
235    /// to allocate memory to in a way that gives better TLB efficiency.
236    pub const DMA_ATTR_ALLOC_SINGLE_PAGES: Attrs = Attrs(bindings::DMA_ATTR_ALLOC_SINGLE_PAGES);
237
238    /// This tells the DMA-mapping subsystem to suppress allocation failure reports (similarly to
239    /// `__GFP_NOWARN`).
240    pub const DMA_ATTR_NO_WARN: Attrs = Attrs(bindings::DMA_ATTR_NO_WARN);
241
242    /// Indicates that the buffer is fully accessible at an elevated privilege level (and
243    /// ideally inaccessible or at least read-only at lesser-privileged levels).
244    pub const DMA_ATTR_PRIVILEGED: Attrs = Attrs(bindings::DMA_ATTR_PRIVILEGED);
245}
246
247/// An abstraction of the `dma_alloc_coherent` API.
248///
249/// This is an abstraction around the `dma_alloc_coherent` API which is used to allocate and map
250/// large coherent DMA regions.
251///
252/// A [`CoherentAllocation`] instance contains a pointer to the allocated region (in the
253/// processor's virtual address space) and the device address which can be given to the device
254/// as the DMA address base of the region. The region is released once [`CoherentAllocation`]
255/// is dropped.
256///
257/// # Invariants
258///
259/// - For the lifetime of an instance of [`CoherentAllocation`], the `cpu_addr` is a valid pointer
260///   to an allocated region of coherent memory and `dma_handle` is the DMA address base of the
261///   region.
262/// - The size in bytes of the allocation is equal to `size_of::<T> * count`.
263/// - `size_of::<T> * count` fits into a `usize`.
264// TODO
265//
266// DMA allocations potentially carry device resources (e.g.IOMMU mappings), hence for soundness
267// reasons DMA allocation would need to be embedded in a `Devres` container, in order to ensure
268// that device resources can never survive device unbind.
269//
270// However, it is neither desirable nor necessary to protect the allocated memory of the DMA
271// allocation from surviving device unbind; it would require RCU read side critical sections to
272// access the memory, which may require subsequent unnecessary copies.
273//
274// Hence, find a way to revoke the device resources of a `CoherentAllocation`, but not the
275// entire `CoherentAllocation` including the allocated memory itself.
276pub struct CoherentAllocation<T: AsBytes + FromBytes> {
277    dev: ARef<device::Device>,
278    dma_handle: bindings::dma_addr_t,
279    count: usize,
280    cpu_addr: *mut T,
281    dma_attrs: Attrs,
282}
283
284impl<T: AsBytes + FromBytes> CoherentAllocation<T> {
285    /// Allocates a region of `size_of::<T> * count` of coherent memory.
286    ///
287    /// # Examples
288    ///
289    /// ```
290    /// # use kernel::device::{Bound, Device};
291    /// use kernel::dma::{attrs::*, CoherentAllocation};
292    ///
293    /// # fn test(dev: &Device<Bound>) -> Result {
294    /// let c: CoherentAllocation<u64> =
295    ///     CoherentAllocation::alloc_attrs(dev, 4, GFP_KERNEL, DMA_ATTR_NO_WARN)?;
296    /// # Ok::<(), Error>(()) }
297    /// ```
298    pub fn alloc_attrs(
299        dev: &device::Device<Bound>,
300        count: usize,
301        gfp_flags: kernel::alloc::Flags,
302        dma_attrs: Attrs,
303    ) -> Result<CoherentAllocation<T>> {
304        build_assert!(
305            core::mem::size_of::<T>() > 0,
306            "It doesn't make sense for the allocated type to be a ZST"
307        );
308
309        let size = count
310            .checked_mul(core::mem::size_of::<T>())
311            .ok_or(EOVERFLOW)?;
312        let mut dma_handle = 0;
313        // SAFETY: Device pointer is guaranteed as valid by the type invariant on `Device`.
314        let ret = unsafe {
315            bindings::dma_alloc_attrs(
316                dev.as_raw(),
317                size,
318                &mut dma_handle,
319                gfp_flags.as_raw(),
320                dma_attrs.as_raw(),
321            )
322        };
323        if ret.is_null() {
324            return Err(ENOMEM);
325        }
326        // INVARIANT:
327        // - We just successfully allocated a coherent region which is accessible for
328        //   `count` elements, hence the cpu address is valid. We also hold a refcounted reference
329        //   to the device.
330        // - The allocated `size` is equal to `size_of::<T> * count`.
331        // - The allocated `size` fits into a `usize`.
332        Ok(Self {
333            dev: dev.into(),
334            dma_handle,
335            count,
336            cpu_addr: ret.cast::<T>(),
337            dma_attrs,
338        })
339    }
340
341    /// Performs the same functionality as [`CoherentAllocation::alloc_attrs`], except the
342    /// `dma_attrs` is 0 by default.
343    pub fn alloc_coherent(
344        dev: &device::Device<Bound>,
345        count: usize,
346        gfp_flags: kernel::alloc::Flags,
347    ) -> Result<CoherentAllocation<T>> {
348        CoherentAllocation::alloc_attrs(dev, count, gfp_flags, Attrs(0))
349    }
350
351    /// Returns the number of elements `T` in this allocation.
352    ///
353    /// Note that this is not the size of the allocation in bytes, which is provided by
354    /// [`Self::size`].
355    pub fn count(&self) -> usize {
356        self.count
357    }
358
359    /// Returns the size in bytes of this allocation.
360    pub fn size(&self) -> usize {
361        // INVARIANT: The type invariant of `Self` guarantees that `size_of::<T> * count` fits into
362        // a `usize`.
363        self.count * core::mem::size_of::<T>()
364    }
365
366    /// Returns the base address to the allocated region in the CPU's virtual address space.
367    pub fn start_ptr(&self) -> *const T {
368        self.cpu_addr
369    }
370
371    /// Returns the base address to the allocated region in the CPU's virtual address space as
372    /// a mutable pointer.
373    pub fn start_ptr_mut(&mut self) -> *mut T {
374        self.cpu_addr
375    }
376
377    /// Returns a DMA handle which may be given to the device as the DMA address base of
378    /// the region.
379    pub fn dma_handle(&self) -> bindings::dma_addr_t {
380        self.dma_handle
381    }
382
383    /// Returns a DMA handle starting at `offset` (in units of `T`) which may be given to the
384    /// device as the DMA address base of the region.
385    ///
386    /// Returns `EINVAL` if `offset` is not within the bounds of the allocation.
387    pub fn dma_handle_with_offset(&self, offset: usize) -> Result<bindings::dma_addr_t> {
388        if offset >= self.count {
389            Err(EINVAL)
390        } else {
391            // INVARIANT: The type invariant of `Self` guarantees that `size_of::<T> * count` fits
392            // into a `usize`, and `offset` is inferior to `count`.
393            Ok(self.dma_handle + (offset * core::mem::size_of::<T>()) as bindings::dma_addr_t)
394        }
395    }
396
397    /// Common helper to validate a range applied from the allocated region in the CPU's virtual
398    /// address space.
399    fn validate_range(&self, offset: usize, count: usize) -> Result {
400        if offset.checked_add(count).ok_or(EOVERFLOW)? > self.count {
401            return Err(EINVAL);
402        }
403        Ok(())
404    }
405
406    /// Returns the data from the region starting from `offset` as a slice.
407    /// `offset` and `count` are in units of `T`, not the number of bytes.
408    ///
409    /// For ringbuffer type of r/w access or use-cases where the pointer to the live data is needed,
410    /// [`CoherentAllocation::start_ptr`] or [`CoherentAllocation::start_ptr_mut`] could be used
411    /// instead.
412    ///
413    /// # Safety
414    ///
415    /// * Callers must ensure that the device does not read/write to/from memory while the returned
416    ///   slice is live.
417    /// * Callers must ensure that this call does not race with a write to the same region while
418    ///   the returned slice is live.
419    pub unsafe fn as_slice(&self, offset: usize, count: usize) -> Result<&[T]> {
420        self.validate_range(offset, count)?;
421        // SAFETY:
422        // - The pointer is valid due to type invariant on `CoherentAllocation`,
423        //   we've just checked that the range and index is within bounds. The immutability of the
424        //   data is also guaranteed by the safety requirements of the function.
425        // - `offset + count` can't overflow since it is smaller than `self.count` and we've checked
426        //   that `self.count` won't overflow early in the constructor.
427        Ok(unsafe { core::slice::from_raw_parts(self.cpu_addr.add(offset), count) })
428    }
429
430    /// Performs the same functionality as [`CoherentAllocation::as_slice`], except that a mutable
431    /// slice is returned.
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    pub unsafe fn as_slice_mut(&mut self, offset: usize, count: usize) -> Result<&mut [T]> {
440        self.validate_range(offset, count)?;
441        // SAFETY:
442        // - The pointer is valid due to type invariant on `CoherentAllocation`,
443        //   we've just checked that the range and index is within bounds. The immutability of the
444        //   data is also guaranteed by the safety requirements of the function.
445        // - `offset + count` can't overflow since it is smaller than `self.count` and we've checked
446        //   that `self.count` won't overflow early in the constructor.
447        Ok(unsafe { core::slice::from_raw_parts_mut(self.cpu_addr.add(offset), count) })
448    }
449
450    /// Writes data to the region starting from `offset`. `offset` is in units of `T`, not the
451    /// number of bytes.
452    ///
453    /// # Safety
454    ///
455    /// * Callers must ensure that the device does not read/write to/from memory while the returned
456    ///   slice is live.
457    /// * Callers must ensure that this call does not race with a read or write to the same region
458    ///   that overlaps with this write.
459    ///
460    /// # Examples
461    ///
462    /// ```
463    /// # fn test(alloc: &mut kernel::dma::CoherentAllocation<u8>) -> Result {
464    /// let somedata: [u8; 4] = [0xf; 4];
465    /// let buf: &[u8] = &somedata;
466    /// // SAFETY: There is no concurrent HW operation on the device and no other R/W access to the
467    /// // region.
468    /// unsafe { alloc.write(buf, 0)?; }
469    /// # Ok::<(), Error>(()) }
470    /// ```
471    pub unsafe fn write(&mut self, src: &[T], offset: usize) -> Result {
472        self.validate_range(offset, src.len())?;
473        // SAFETY:
474        // - The pointer is valid due to type invariant on `CoherentAllocation`
475        //   and we've just checked that the range and index is within bounds.
476        // - `offset + count` can't overflow since it is smaller than `self.count` and we've checked
477        //   that `self.count` won't overflow early in the constructor.
478        unsafe {
479            core::ptr::copy_nonoverlapping(src.as_ptr(), self.cpu_addr.add(offset), src.len())
480        };
481        Ok(())
482    }
483
484    /// Returns a pointer to an element from the region with bounds checking. `offset` is in
485    /// units of `T`, not the number of bytes.
486    ///
487    /// Public but hidden since it should only be used from [`dma_read`] and [`dma_write`] macros.
488    #[doc(hidden)]
489    pub fn item_from_index(&self, offset: usize) -> Result<*mut T> {
490        if offset >= self.count {
491            return Err(EINVAL);
492        }
493        // SAFETY:
494        // - The pointer is valid due to type invariant on `CoherentAllocation`
495        // and we've just checked that the range and index is within bounds.
496        // - `offset` can't overflow since it is smaller than `self.count` and we've checked
497        // that `self.count` won't overflow early in the constructor.
498        Ok(unsafe { self.cpu_addr.add(offset) })
499    }
500
501    /// Reads the value of `field` and ensures that its type is [`FromBytes`].
502    ///
503    /// # Safety
504    ///
505    /// This must be called from the [`dma_read`] macro which ensures that the `field` pointer is
506    /// validated beforehand.
507    ///
508    /// Public but hidden since it should only be used from [`dma_read`] macro.
509    #[doc(hidden)]
510    pub unsafe fn field_read<F: FromBytes>(&self, field: *const F) -> F {
511        // SAFETY:
512        // - By the safety requirements field is valid.
513        // - Using read_volatile() here is not sound as per the usual rules, the usage here is
514        // a special exception with the following notes in place. When dealing with a potential
515        // race from a hardware or code outside kernel (e.g. user-space program), we need that
516        // read on a valid memory is not UB. Currently read_volatile() is used for this, and the
517        // rationale behind is that it should generate the same code as READ_ONCE() which the
518        // kernel already relies on to avoid UB on data races. Note that the usage of
519        // read_volatile() is limited to this particular case, it cannot be used to prevent
520        // the UB caused by racing between two kernel functions nor do they provide atomicity.
521        unsafe { field.read_volatile() }
522    }
523
524    /// Writes a value to `field` and ensures that its type is [`AsBytes`].
525    ///
526    /// # Safety
527    ///
528    /// This must be called from the [`dma_write`] macro which ensures that the `field` pointer is
529    /// validated beforehand.
530    ///
531    /// Public but hidden since it should only be used from [`dma_write`] macro.
532    #[doc(hidden)]
533    pub unsafe fn field_write<F: AsBytes>(&self, field: *mut F, val: F) {
534        // SAFETY:
535        // - By the safety requirements field is valid.
536        // - Using write_volatile() here is not sound as per the usual rules, the usage here is
537        // a special exception with the following notes in place. When dealing with a potential
538        // race from a hardware or code outside kernel (e.g. user-space program), we need that
539        // write on a valid memory is not UB. Currently write_volatile() is used for this, and the
540        // rationale behind is that it should generate the same code as WRITE_ONCE() which the
541        // kernel already relies on to avoid UB on data races. Note that the usage of
542        // write_volatile() is limited to this particular case, it cannot be used to prevent
543        // the UB caused by racing between two kernel functions nor do they provide atomicity.
544        unsafe { field.write_volatile(val) }
545    }
546}
547
548/// Note that the device configured to do DMA must be halted before this object is dropped.
549impl<T: AsBytes + FromBytes> Drop for CoherentAllocation<T> {
550    fn drop(&mut self) {
551        let size = self.count * core::mem::size_of::<T>();
552        // SAFETY: Device pointer is guaranteed as valid by the type invariant on `Device`.
553        // The cpu address, and the dma handle are valid due to the type invariants on
554        // `CoherentAllocation`.
555        unsafe {
556            bindings::dma_free_attrs(
557                self.dev.as_raw(),
558                size,
559                self.cpu_addr.cast(),
560                self.dma_handle,
561                self.dma_attrs.as_raw(),
562            )
563        }
564    }
565}
566
567// SAFETY: It is safe to send a `CoherentAllocation` to another thread if `T`
568// can be sent to another thread.
569unsafe impl<T: AsBytes + FromBytes + Send> Send for CoherentAllocation<T> {}
570
571/// Reads a field of an item from an allocated region of structs.
572///
573/// # Examples
574///
575/// ```
576/// use kernel::device::Device;
577/// use kernel::dma::{attrs::*, CoherentAllocation};
578///
579/// struct MyStruct { field: u32, }
580///
581/// // SAFETY: All bit patterns are acceptable values for `MyStruct`.
582/// unsafe impl kernel::transmute::FromBytes for MyStruct{};
583/// // SAFETY: Instances of `MyStruct` have no uninitialized portions.
584/// unsafe impl kernel::transmute::AsBytes for MyStruct{};
585///
586/// # fn test(alloc: &kernel::dma::CoherentAllocation<MyStruct>) -> Result {
587/// let whole = kernel::dma_read!(alloc[2]);
588/// let field = kernel::dma_read!(alloc[1].field);
589/// # Ok::<(), Error>(()) }
590/// ```
591#[macro_export]
592macro_rules! dma_read {
593    ($dma:expr, $idx: expr, $($field:tt)*) => {{
594        (|| -> ::core::result::Result<_, $crate::error::Error> {
595            let item = $crate::dma::CoherentAllocation::item_from_index(&$dma, $idx)?;
596            // SAFETY: `item_from_index` ensures that `item` is always a valid pointer and can be
597            // dereferenced. The compiler also further validates the expression on whether `field`
598            // is a member of `item` when expanded by the macro.
599            unsafe {
600                let ptr_field = ::core::ptr::addr_of!((*item) $($field)*);
601                ::core::result::Result::Ok(
602                    $crate::dma::CoherentAllocation::field_read(&$dma, ptr_field)
603                )
604            }
605        })()
606    }};
607    ($dma:ident [ $idx:expr ] $($field:tt)* ) => {
608        $crate::dma_read!($dma, $idx, $($field)*)
609    };
610    ($($dma:ident).* [ $idx:expr ] $($field:tt)* ) => {
611        $crate::dma_read!($($dma).*, $idx, $($field)*)
612    };
613}
614
615/// Writes to a field of an item from an allocated region of structs.
616///
617/// # Examples
618///
619/// ```
620/// use kernel::device::Device;
621/// use kernel::dma::{attrs::*, CoherentAllocation};
622///
623/// struct MyStruct { member: u32, }
624///
625/// // SAFETY: All bit patterns are acceptable values for `MyStruct`.
626/// unsafe impl kernel::transmute::FromBytes for MyStruct{};
627/// // SAFETY: Instances of `MyStruct` have no uninitialized portions.
628/// unsafe impl kernel::transmute::AsBytes for MyStruct{};
629///
630/// # fn test(alloc: &kernel::dma::CoherentAllocation<MyStruct>) -> Result {
631/// kernel::dma_write!(alloc[2].member = 0xf);
632/// kernel::dma_write!(alloc[1] = MyStruct { member: 0xf });
633/// # Ok::<(), Error>(()) }
634/// ```
635#[macro_export]
636macro_rules! dma_write {
637    ($dma:ident [ $idx:expr ] $($field:tt)*) => {{
638        $crate::dma_write!($dma, $idx, $($field)*)
639    }};
640    ($($dma:ident).* [ $idx:expr ] $($field:tt)* ) => {{
641        $crate::dma_write!($($dma).*, $idx, $($field)*)
642    }};
643    ($dma:expr, $idx: expr, = $val:expr) => {
644        (|| -> ::core::result::Result<_, $crate::error::Error> {
645            let item = $crate::dma::CoherentAllocation::item_from_index(&$dma, $idx)?;
646            // SAFETY: `item_from_index` ensures that `item` is always a valid item.
647            unsafe { $crate::dma::CoherentAllocation::field_write(&$dma, item, $val) }
648            ::core::result::Result::Ok(())
649        })()
650    };
651    ($dma:expr, $idx: expr, $(.$field:ident)* = $val:expr) => {
652        (|| -> ::core::result::Result<_, $crate::error::Error> {
653            let item = $crate::dma::CoherentAllocation::item_from_index(&$dma, $idx)?;
654            // SAFETY: `item_from_index` ensures that `item` is always a valid pointer and can be
655            // dereferenced. The compiler also further validates the expression on whether `field`
656            // is a member of `item` when expanded by the macro.
657            unsafe {
658                let ptr_field = ::core::ptr::addr_of_mut!((*item) $(.$field)*);
659                $crate::dma::CoherentAllocation::field_write(&$dma, ptr_field, $val)
660            }
661            ::core::result::Result::Ok(())
662        })()
663    };
664}