Skip to main content

kernel/
io.rs

1// SPDX-License-Identifier: GPL-2.0
2
3//! Memory-mapped IO.
4//!
5//! C header: [`include/asm-generic/io.h`](srctree/include/asm-generic/io.h)
6
7use core::{
8    marker::PhantomData,
9    mem::MaybeUninit,
10    num::TryFromIntError, //
11};
12
13use crate::{
14    bindings,
15    fmt,
16    mem::{
17        AsRepr,
18        AsReprMut, //
19    },
20    prelude::*,
21    ptr::{
22        Alignment,
23        KnownSize, //
24    }, //
25};
26
27#[cfg(CONFIG_HAS_IOMEM)]
28pub mod mem;
29pub mod poll;
30pub mod register;
31pub mod resource;
32
33pub use crate::register;
34pub use resource::Resource;
35
36use register::LocatedRegister;
37
38/// Physical address type.
39///
40/// This is a type alias to either `u32` or `u64` depending on the config option
41/// `CONFIG_PHYS_ADDR_T_64BIT`, and it can be a u64 even on 32-bit architectures.
42pub type PhysAddr = bindings::phys_addr_t;
43
44/// Resource size type.
45///
46/// This wraps either `u32` or `u64` depending on the config option
47/// `CONFIG_PHYS_ADDR_T_64BIT`, and it can be a `u64` even on 32-bit architectures.
48///
49/// # Examples
50///
51/// ```
52/// use kernel::io::ResourceSize;
53///
54/// let size = ResourceSize::from_raw(0x1000);
55/// assert_eq!(size.into_raw(), 0x1000);
56///
57/// // Round-trips through the raw C type.
58/// let raw: kernel::bindings::resource_size_t = size.into();
59/// assert_eq!(ResourceSize::from(raw), size);
60///
61/// // Fallible conversion to `usize` (can truncate on 32-bit).
62/// assert_eq!(usize::try_from(size)?, 0x1000);
63/// # Ok::<(), core::num::TryFromIntError>(())
64/// ```
65#[repr(transparent)]
66#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
67pub struct ResourceSize(bindings::resource_size_t);
68
69impl ResourceSize {
70    /// Creates a resource size from the raw C type.
71    #[inline]
72    pub const fn from_raw(value: bindings::resource_size_t) -> Self {
73        Self(value)
74    }
75
76    /// Turns this resource size into the raw C type.
77    #[inline]
78    pub const fn into_raw(self) -> bindings::resource_size_t {
79        self.0
80    }
81}
82
83impl fmt::Debug for ResourceSize {
84    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
85        write!(f, "{:#x}", self.0)
86    }
87}
88
89impl From<bindings::resource_size_t> for ResourceSize {
90    #[inline]
91    fn from(value: bindings::resource_size_t) -> Self {
92        Self::from_raw(value)
93    }
94}
95
96impl From<ResourceSize> for bindings::resource_size_t {
97    #[inline]
98    fn from(value: ResourceSize) -> Self {
99        value.into_raw()
100    }
101}
102
103impl TryFrom<ResourceSize> for usize {
104    type Error = TryFromIntError;
105
106    #[inline]
107    fn try_from(value: ResourceSize) -> Result<Self, Self::Error> {
108        Self::try_from(value.into_raw())
109    }
110}
111
112/// Untyped I/O region.
113///
114/// This type can be used when an I/O region without known type information has a compile-time known
115/// minimum size (and a runtime known actual size).
116///
117/// # Invariants
118///
119/// - Size of the region is at least as large as the `SIZE` generic parameter.
120/// - Size of the region is multiple of 4.
121#[repr(C, align(4))]
122#[derive(FromBytes)]
123pub struct Region<const SIZE: usize = 0> {
124    inner: [u8],
125}
126
127impl<const SIZE: usize> Region<SIZE> {
128    /// Create a raw mutable pointer from given base address and size.
129    ///
130    /// `size` should be at least as large as the minimum size `SIZE`, and `base` and `size` should
131    /// be 4-byte aligned to uphold the type invariant.
132    ///
133    /// Just like other methods on raw pointers, it is not unsafe to create a raw pointer
134    /// that does not uphold the type invariants. However such pointers are not valid.
135    #[inline]
136    pub fn ptr_from_raw_parts_mut(base: *mut u8, size: usize) -> *mut Self {
137        core::ptr::slice_from_raw_parts_mut(base, size) as *mut Region<SIZE>
138    }
139
140    /// Create a raw mutable pointer from given base address and size.
141    ///
142    /// The alignment of `base` is checked, and `size` is checked against the minimum size specified
143    /// via const generics.
144    #[inline]
145    pub fn ptr_try_from_raw_parts_mut(base: *mut u8, size: usize) -> Result<*mut Self> {
146        if size < SIZE || base.align_offset(4) != 0 || !size.is_multiple_of(4) {
147            return Err(EINVAL);
148        }
149
150        Ok(Self::ptr_from_raw_parts_mut(base, size))
151    }
152}
153
154impl<const SIZE: usize> KnownSize for Region<SIZE> {
155    const MIN_SIZE: usize = SIZE;
156    // Alignment of 4 is the most common; different base types can be added once required.
157    const MIN_ALIGN: Alignment = Alignment::new::<4>();
158
159    #[inline(always)]
160    fn size(p: *const Self) -> usize {
161        (p as *const [u8]).len()
162    }
163}
164
165// SAFETY:
166// - Values read from I/O are always treated as initialized.
167// - Per type invariant the size is multiple of 4 and the type is 4-byte aligned, so it is padding
168//   free.
169//
170// This cannot be derived as `derive(IntoBytes)` as the padding free property comes from type
171// invariant which the macro does not know.
172unsafe impl<const SIZE: usize> IntoBytes for Region<SIZE> {
173    #[inline]
174    #[allow(unused)] // Rust 1.87+ stops requiring this and will emit unused warnings.
175    fn only_derive_is_allowed_to_implement_this_trait() {}
176}
177
178/// Raw representation of an MMIO region.
179///
180/// `MmioRaw<T>` is equivalent to `T __iomem *` in C.
181///
182/// By itself, the existence of an instance of this structure does not provide any guarantees that
183/// the represented MMIO region does exist or is properly mapped.
184///
185/// Instead, the bus specific MMIO implementation must convert this raw representation into an
186/// `Mmio` instance providing the actual memory accessors. Only by the conversion into an `Mmio`
187/// structure any guarantees are given.
188pub struct MmioRaw<T: ?Sized> {
189    /// Pointer is in I/O address space.
190    ///
191    /// The provenance does not matter, only the address and metadata do.
192    ptr: *mut T,
193}
194
195impl<T: ?Sized> Copy for MmioRaw<T> {}
196impl<T: ?Sized> Clone for MmioRaw<T> {
197    #[inline]
198    fn clone(&self) -> Self {
199        *self
200    }
201}
202
203// SAFETY: `MmioRaw` is just an address, so is thread-safe.
204unsafe impl<T: ?Sized> Send for MmioRaw<T> {}
205// SAFETY: `MmioRaw` is just an address, so is thread-safe.
206unsafe impl<T: ?Sized> Sync for MmioRaw<T> {}
207
208impl<T> MmioRaw<T> {
209    /// Create a `MmioRaw` from address.
210    #[inline]
211    pub fn new(addr: usize) -> Self {
212        Self {
213            ptr: core::ptr::without_provenance_mut(addr),
214        }
215    }
216}
217
218impl<const SIZE: usize> MmioRaw<Region<SIZE>> {
219    /// Create a `MmioRaw` representing a I/O region with given size.
220    ///
221    /// The size is checked against the minimum size specified via const generics.
222    #[inline]
223    pub fn new_region(addr: usize, size: usize) -> Result<Self> {
224        Ok(Self {
225            ptr: Region::ptr_try_from_raw_parts_mut(core::ptr::without_provenance_mut(addr), size)?,
226        })
227    }
228}
229
230impl<T: ?Sized + KnownSize> MmioRaw<T> {
231    /// Returns the base address of the MMIO region.
232    #[inline]
233    pub fn addr(&self) -> usize {
234        self.ptr.addr()
235    }
236
237    /// Returns the size of the MMIO region.
238    #[inline]
239    pub fn size(&self) -> usize {
240        KnownSize::size(self.ptr)
241    }
242}
243
244/// Checks whether an access of type `U` at the given `base` and the given `offset`
245/// is valid within this region.
246///
247/// The `base` is used for alignment checking only. This can be set to 0 to skip the check.
248#[inline]
249const fn offset_valid<U>(base: usize, offset: usize, size: usize) -> bool {
250    if let Some(end) = offset.checked_add(size_of::<U>()) {
251        end <= size && (base.wrapping_add(offset) % align_of::<U>() == 0)
252    } else {
253        false
254    }
255}
256
257/// Returns a view for a given `offset`, performing compile-time bound checks.
258// Always inline to optimize out error path of `build_assert`.
259#[inline(always)]
260fn io_view_assert<'a, IO: Io<'a>, U>(
261    this: IO,
262    offset: usize,
263) -> <IO::Backend as IoBackend>::View<'a, U> {
264    // We cannot check alignment with `offset_valid` using `ptr.addr()`. So set 0 for it and
265    // ensure alignment by checking that the alignment of `U` is smaller or equal to the
266    // alignment of `IO::Target`.
267    const_assert!(Alignment::of::<U>().as_usize() <= IO::Target::MIN_ALIGN.as_usize());
268    build_assert!(offset_valid::<U>(0, offset, IO::Target::MIN_SIZE));
269
270    let view = this.as_view();
271    let ptr = IO::Backend::as_ptr(view);
272    let projected_ptr = ptr.cast::<U>().wrapping_byte_add(offset);
273    // SAFETY: `offset_valid` checks for size and alignment and therefore `projected_ptr` is a
274    // valid projection.
275    unsafe { IO::Backend::project_view(view, projected_ptr) }
276}
277
278/// Returns a view for a given `offset`, performing runtime bound checks.
279#[inline]
280fn io_view<'a, IO: Io<'a>, U>(
281    this: IO,
282    offset: usize,
283) -> Result<<IO::Backend as IoBackend>::View<'a, U>> {
284    let view = this.as_view();
285    let ptr = IO::Backend::as_ptr(view);
286
287    if !offset_valid::<U>(ptr.addr(), offset, KnownSize::size(ptr)) {
288        return Err(EINVAL);
289    }
290
291    let projected_ptr = ptr.cast::<U>().wrapping_byte_add(offset);
292    // SAFETY: `offset_valid` checks for size and alignment and therefore `projected_ptr` is a
293    // valid projection.
294    Ok(unsafe { IO::Backend::project_view(view, projected_ptr) })
295}
296
297/// Returns the primitive view of a I/O view.
298#[inline]
299fn io_view_as_repr<'a, IO: Io<'a, Target = T>, T: AsRepr>(
300    this: IO,
301) -> <IO::Backend as IoBackend>::View<'a, T::Repr> {
302    let view = this.as_view();
303
304    // SAFETY: `AsRepr` guarantees layout compatibility.
305    unsafe { IO::Backend::project_view(view, IO::Backend::as_ptr(view).cast::<T::Repr>()) }
306}
307
308/// I/O backends.
309///
310/// This is an abstract representation to be implemented by arbitrary I/O
311/// backends (e.g. MMIO, PCI config space, etc.).
312///
313/// The base trait only defines the projection operations; which I/O methods are available depends
314/// on which [`IoCapable<T>`] traits are implemented for the type. For example, for MMIO regions,
315/// all widths (u8, u16, u32, and u64 on 64-bit systems) are typically supported. For PCI
316/// configuration space, u8, u16, and u32 are supported but u64 is not.
317///
318/// This trait is separate from the `Io` trait as multiple different I/O types may share the same
319/// operation.
320pub trait IoBackend {
321    /// View type for this I/O backend.
322    type View<'a, T: ?Sized + KnownSize>: IoBase<'a, Backend = Self, Target = T>;
323
324    /// Convert a `view` to a raw pointer for projection.
325    ///
326    /// The returned pointer is private implementation detail of the backend; it is likely not
327    /// valid. It should not be dereferenced.
328    fn as_ptr<'a, T: ?Sized + KnownSize>(view: Self::View<'a, T>) -> *mut T;
329
330    /// Project `view` to its subregion indicated by `ptr`.
331    ///
332    /// If input `view` is valid, returned view must also be valid.
333    ///
334    /// # Safety
335    ///
336    /// `ptr` must be a projection of `Self::as_ptr(view)`.
337    unsafe fn project_view<'a, T: ?Sized + KnownSize, U: ?Sized + KnownSize>(
338        view: Self::View<'a, T>,
339        ptr: *mut U,
340    ) -> Self::View<'a, U>;
341}
342
343/// Trait indicating that an I/O backend supports operations of a certain type and providing an
344/// implementation for these operations.
345///
346/// Different I/O backends can implement this trait to expose only the operations they support.
347///
348/// For example, a PCI configuration space may implement `IoCapable<u8>`, `IoCapable<u16>`,
349/// and `IoCapable<u32>`, but not `IoCapable<u64>`, while an MMIO region on a 64-bit
350/// system might implement all four.
351pub trait IoCapable<T>: IoBackend {
352    /// Performs an I/O read of type `T` at `view` and returns the result.
353    fn io_read<'a>(view: Self::View<'a, T>) -> T;
354
355    /// Performs an I/O write of `value` at `view`.
356    fn io_write<'a>(view: Self::View<'a, T>, value: T);
357}
358
359/// Trait indicating that an I/O backend supports memory copy operations.
360pub trait IoCopyable: IoBackend {
361    /// Copy contents of `view` to `buffer`.
362    ///
363    /// # Safety
364    ///
365    /// - `buffer` is valid for volatile write for `view.size()` bytes.
366    /// - `buffer` should not overlap with `view`.
367    unsafe fn copy_from_io(view: Self::View<'_, [u8]>, buffer: *mut u8);
368
369    /// Copy contents from `buffer` to `view`.
370    ///
371    /// # Safety
372    ///
373    /// - `buffer` is valid for volatile read for `view.size()` bytes.
374    /// - `buffer` should not overlap with `view`.
375    unsafe fn copy_to_io(view: Self::View<'_, [u8]>, buffer: *const u8);
376
377    /// Copy from `view` and return the value.
378    #[inline]
379    fn copy_read<T: FromBytes>(view: Self::View<'_, T>) -> T {
380        // Project `self` to `[u8]`.
381        let ptr = Self::as_ptr(view);
382        // SAFETY: This is a identity projection.
383        let slice_view = unsafe {
384            Self::project_view(
385                view,
386                core::ptr::slice_from_raw_parts_mut::<u8>(ptr.cast(), size_of::<T>()),
387            )
388        };
389
390        let mut buf = MaybeUninit::<T>::uninit();
391        // SAFETY:
392        // - `buf.as_mut_ptr()` is valid for write for `size_of::<T>()` bytes.
393        // - `buf` is local so `buf.as_mut_ptr()` cannot overlap with `slice_view`.
394        unsafe { Self::copy_from_io(slice_view, buf.as_mut_ptr().cast()) };
395        // SAFETY: `T: FromBytes` guarantee that all bit patterns are valid.
396        unsafe { buf.assume_init() }
397    }
398
399    /// Copy `value` to `view`.
400    ///
401    /// Destructor of `value` will not be executed, consistent with [`zerocopy::transmute`].
402    #[inline]
403    fn copy_write<T: IntoBytes>(view: Self::View<'_, T>, value: T) {
404        // Project `self` to `[u8]`.
405        let ptr = Self::as_ptr(view);
406        // SAFETY: This is a identity projection.
407        let slice_view = unsafe {
408            Self::project_view(
409                view,
410                core::ptr::slice_from_raw_parts_mut::<u8>(ptr.cast(), size_of::<T>()),
411            )
412        };
413
414        // SAFETY:
415        // - `&raw const value` is valid for read for `size_of::<T>()` bytes.
416        // - `value` is local so `&raw const value` cannot overlap with `slice_view`.
417        unsafe { Self::copy_to_io(slice_view, (&raw const value).cast()) };
418        core::mem::forget(value);
419    }
420}
421
422/// Describes a given I/O location: its offset, width, and type to convert the raw value from and
423/// into.
424///
425/// This trait is the key abstraction allowing [`Io::read`], [`Io::write`], and [`Io::update`] (and
426/// their fallible [`try_read`](Io::try_read), [`try_write`](Io::try_write) and
427/// [`try_update`](Io::try_update) counterparts) to work uniformly with both raw [`usize`] offsets
428/// (for primitive types like [`u32`]) and typed ones (like those generated by the [`register!`]
429/// macro).
430///
431/// An `IoLoc<Base, T>` carries the following pieces of information:
432///
433/// - The valid `Base` to operate on. For most registers, this should be [`Region`].
434/// - The offset to access (returned by [`IoLoc::offset`]),
435/// - The type `T` in which the data is returned or provided.
436///
437/// `T` is not necessarily the type for underlying I/O operation. Methods that take `IoLoc` have `T:
438/// AsRepr` bound and the `<T as AsRepr>::Repr` type would be used to perform I/O and converted to
439/// `T` instead.
440pub trait IoLoc<Base: ?Sized, T> {
441    /// Consumes `self` and returns the offset of this location.
442    fn offset(self) -> usize;
443}
444
445/// Implements [`IoLoc<Region<SIZE>, $ty>`] for [`usize`], allowing [`usize`] to be used as a
446/// parameter of [`Io::read`] and [`Io::write`].
447macro_rules! impl_usize_ioloc {
448    ($($ty:ty),*) => {
449        $(
450            impl<const SIZE: usize> IoLoc<Region<SIZE>, $ty> for usize {
451                #[inline(always)]
452                fn offset(self) -> usize {
453                    self
454                }
455            }
456        )*
457    }
458}
459
460// Provide the ability to read any primitive type from a [`usize`].
461impl_usize_ioloc!(u8, u16, u32, u64);
462
463/// Types implementing this trait (e.g. MMIO BARs or PCI config regions)
464/// can perform I/O operations on regions of memory.
465///
466/// This trait defines which backend shall be used for I/O operations and provides a method to
467/// convert into [`IoBackend::View`]. Users should use the [`Io`] trait which provides the actual
468/// methods to perform I/O operations.
469///
470/// This should be implemented on cheaply copyable handles, such as references or view types.
471pub trait IoBase<'a>: Copy {
472    /// Type that defines all I/O operations.
473    type Backend: IoBackend;
474
475    /// Type of this I/O region. For untyped regions, [`Region`] can be used.
476    type Target: ?Sized + KnownSize;
477
478    /// Return a view that covers the full region.
479    fn as_view(self) -> <Self::Backend as IoBackend>::View<'a, Self::Target>;
480}
481
482/// Extension trait to provide I/O operation methods to types that implement [`IoBase`].
483///
484/// This trait provides:
485/// - Helper methods for offset validation and address calculation
486/// - Fallible (runtime checked) accessors for different data widths
487///
488/// Which I/O methods are available depends on the associated [`IoBackend`] implementation.
489pub trait Io<'a>: IoBase<'a> {
490    /// Returns the size of this I/O region.
491    #[inline]
492    fn size(self) -> usize {
493        KnownSize::size(Self::Backend::as_ptr(self.as_view()))
494    }
495
496    /// Returns the length of the slice in number of elements.
497    #[inline]
498    fn len<T>(self) -> usize
499    where
500        Self: Io<'a, Target = [T]>,
501    {
502        Self::Backend::as_ptr(self.as_view()).len()
503    }
504
505    /// Returns `true` if the slice has a length of 0.
506    #[inline]
507    fn is_empty<T>(self) -> bool
508    where
509        Self: Io<'a, Target = [T]>,
510    {
511        self.len() == 0
512    }
513
514    /// Convert into a different typed I/O view.
515    ///
516    /// The target type must be known (statically) to be of the same or smaller size to current
517    /// type, and the current view must be properly aligned for the target type.
518    ///
519    /// # Examples
520    ///
521    /// ```no_run
522    /// use kernel::io::{
523    ///     io_project,
524    ///     Mmio,
525    ///     Io,
526    ///     Region,
527    /// };
528    /// #[derive(FromBytes, IntoBytes)]
529    /// #[repr(C)]
530    /// struct MyStruct { field: u32, }
531    ///
532    /// # fn test(mmio: &Mmio<'_, Region<0x1000>>) {
533    /// // let mmio: Mmio<'_, Region<0x1000>>;
534    /// let whole: Mmio<'_, MyStruct> = mmio.cast();
535    /// # }
536    /// ```
537    #[inline]
538    fn cast<U>(self) -> <Self::Backend as IoBackend>::View<'a, U>
539    where
540        Self::Target: FromBytes + IntoBytes,
541        U: FromBytes + IntoBytes,
542    {
543        let view = self.as_view();
544        let ptr = Self::Backend::as_ptr(view);
545
546        const_assert!(size_of::<U>() <= Self::Target::MIN_SIZE);
547        const_assert!(align_of::<U>() <= Self::Target::MIN_ALIGN.as_usize());
548
549        // SAFETY: We have checked bounds and alignment, so this is a valid projection.
550        unsafe { Self::Backend::project_view(view, ptr.cast()) }
551    }
552
553    /// Try to convert into a different typed I/O view.
554    ///
555    /// A runtime check is performed to ensure that the target type is of same or smaller size to
556    /// current type, and the current view is properly aligned for the target type. Returns
557    /// `Err(EINVAL)` if the runtime check fails.
558    ///
559    /// # Examples
560    ///
561    /// ```no_run
562    /// use kernel::io::{
563    ///     io_project,
564    ///     Mmio,
565    ///     Io,
566    ///     Region,
567    /// };
568    /// #[derive(FromBytes, IntoBytes)]
569    /// #[repr(C)]
570    /// struct MyStruct { field: u32, }
571    ///
572    /// # fn test(mmio: &Mmio<'_, Region>) -> Result {
573    /// // let mmio: Mmio<'_, Region>;
574    /// let whole: Mmio<'_, MyStruct> = mmio.try_cast()?;
575    /// # Ok::<(), Error>(()) }
576    /// ```
577    #[inline]
578    fn try_cast<U>(self) -> Result<<Self::Backend as IoBackend>::View<'a, U>>
579    where
580        Self::Target: FromBytes + IntoBytes,
581        U: FromBytes + IntoBytes,
582    {
583        let view = self.as_view();
584        let ptr = Self::Backend::as_ptr(view);
585
586        if size_of::<U>() > KnownSize::size(ptr) {
587            return Err(EINVAL);
588        }
589
590        if ptr.addr() % align_of::<U>() != 0 {
591            return Err(EINVAL);
592        }
593
594        // SAFETY: We have checked bounds and alignment, so this is a valid projection.
595        Ok(unsafe { Self::Backend::project_view(view, ptr.cast()) })
596    }
597
598    /// Read a value from I/O.
599    ///
600    /// This only works for primitives supported by the I/O backend.
601    ///
602    /// # Examples
603    ///
604    /// ```no_run
605    /// # use kernel::io::*;
606    /// # fn test_read_val(mmio: Mmio<'_, u32>) {
607    /// // let mmio: Mmio<'_, u32>;
608    /// let val: u32 = mmio.read_val();
609    /// # }
610    /// ```
611    #[inline]
612    fn read_val(self) -> Self::Target
613    where
614        Self::Target: AsReprMut,
615        Self::Backend: IoCapable<<Self::Target as AsRepr>::Repr>,
616    {
617        Self::Target::from_repr(Self::Backend::io_read(io_view_as_repr(self)))
618    }
619
620    /// Write a value to I/O.
621    ///
622    /// This only works for primitives supported by the I/O backend.
623    ///
624    /// # Examples
625    ///
626    /// ```no_run
627    /// # use kernel::io::*;
628    /// # fn test_write_val(mmio: Mmio<'_, u32>) {
629    /// // let mmio: Mmio<'_, u32>;
630    /// mmio.write_val(1u32);
631    /// # }
632    /// ```
633    #[inline]
634    fn write_val(self, value: Self::Target)
635    where
636        Self::Target: AsRepr,
637        Self::Backend: IoCapable<<Self::Target as AsRepr>::Repr>,
638    {
639        Self::Backend::io_write(io_view_as_repr(self), Self::Target::into_repr(value))
640    }
641
642    /// Copy-read from I/O memory.
643    ///
644    /// This is equivalent to reading from the I/O memory with byte-wise copy, although the actual
645    /// implementation might be more efficient. There is no atomicity guarantee. Note that for some
646    /// backends (e.g. `Mmio`), this can read different value compared to [`read_val`] as
647    /// byte-swapping is not performed.
648    ///
649    /// [`read_val`]: Io::read_val
650    ///
651    /// # Examples
652    ///
653    /// ```no_run
654    /// # use kernel::io::*;
655    /// # fn test_copy_read(mmio: Mmio<'_, [u8; 6]>) {
656    /// // let mmio: Mmio<'_, [u8; 6]>;
657    /// let val: [u8; 6] = mmio.copy_read();
658    /// # }
659    /// ```
660    #[inline]
661    fn copy_read(self) -> Self::Target
662    where
663        Self::Backend: IoCopyable,
664        Self::Target: Sized + FromBytes,
665    {
666        Self::Backend::copy_read(self.as_view())
667    }
668
669    /// Copy-write to I/O memory.
670    ///
671    /// This is equivalent to writing to the I/O memory with byte-wise copy, although the actual
672    /// implementation might be more efficient. There is no atomicity guarantee. Note that for some
673    /// backends (e.g. `Mmio`), this can write different value compared to [`write_val`] as
674    /// byte-swapping is not performed.
675    ///
676    /// [`write_val`]: Io::write_val
677    ///
678    /// # Examples
679    ///
680    /// ```no_run
681    /// # use kernel::io::*;
682    /// # fn test_copy_write(mmio: Mmio<'_, [u8; 6]>) {
683    /// // let mmio: Mmio<'_, [u8; 6]>;
684    /// mmio.copy_write([0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF]);
685    /// # }
686    /// ```
687    #[inline]
688    fn copy_write(self, value: Self::Target)
689    where
690        Self::Backend: IoCopyable,
691        Self::Target: Sized + IntoBytes,
692    {
693        Self::Backend::copy_write(self.as_view(), value);
694    }
695
696    /// Copy bytes from `data` to I/O memory.
697    ///
698    /// # Panics
699    ///
700    /// This function will panic if the length of `self` differs from the length of `data`, similar
701    /// to [`[u8]::copy_from_slice`].
702    ///
703    /// # Examples
704    ///
705    /// ```no_run
706    /// # use kernel::io::*;
707    /// # fn test_copy_write(mmio: Mmio<'_, [u8]>) {
708    /// // let mmio: Mmio<'_, [u8]>;
709    /// mmio.copy_from_slice(&[0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF]);
710    /// # }
711    /// ```
712    #[inline]
713    fn copy_from_slice(self, data: &[u8])
714    where
715        Self::Backend: IoCopyable,
716        Self: Io<'a, Target = [u8]>,
717    {
718        assert_eq!(self.len(), data.len());
719
720        // SAFETY: `data.as_ptr()` is valid for read for `self.size()` bytes.
721        unsafe {
722            Self::Backend::copy_to_io(self.as_view(), data.as_ptr());
723        }
724    }
725
726    /// Copy bytes from I/O memory to `data`.
727    ///
728    /// # Panics
729    ///
730    /// This function will panic if the length of `self` differs from the length of `data`, similar
731    /// to [`[u8]::copy_from_slice`].
732    ///
733    /// # Examples
734    ///
735    /// ```no_run
736    /// # use kernel::io::*;
737    /// # fn test_copy_write(mmio: Mmio<'_, [u8]>) {
738    /// // let mmio: Mmio<'_, [u8]>;
739    /// let mut buf = [0; 6];
740    /// mmio.copy_to_slice(&mut buf);
741    /// # }
742    /// ```
743    #[inline]
744    fn copy_to_slice(self, data: &mut [u8])
745    where
746        Self::Backend: IoCopyable,
747        Self: Io<'a, Target = [u8]>,
748    {
749        assert_eq!(self.len(), data.len());
750
751        // SAFETY: `data.as_mut_ptr()` is valid for write for `self.size()` bytes.
752        unsafe {
753            Self::Backend::copy_from_io(self.as_view(), data.as_mut_ptr());
754        }
755    }
756
757    /// Fallible 8-bit read with runtime bounds check.
758    #[inline(always)]
759    fn try_read8(self, offset: usize) -> Result<u8>
760    where
761        usize: IoLoc<Self::Target, u8>,
762        Self::Backend: IoCapable<u8>,
763    {
764        self.try_read(offset)
765    }
766
767    /// Fallible 16-bit read with runtime bounds check.
768    #[inline(always)]
769    fn try_read16(self, offset: usize) -> Result<u16>
770    where
771        usize: IoLoc<Self::Target, u16>,
772        Self::Backend: IoCapable<u16>,
773    {
774        self.try_read(offset)
775    }
776
777    /// Fallible 32-bit read with runtime bounds check.
778    #[inline(always)]
779    fn try_read32(self, offset: usize) -> Result<u32>
780    where
781        usize: IoLoc<Self::Target, u32>,
782        Self::Backend: IoCapable<u32>,
783    {
784        self.try_read(offset)
785    }
786
787    /// Fallible 64-bit read with runtime bounds check.
788    #[inline(always)]
789    fn try_read64(self, offset: usize) -> Result<u64>
790    where
791        usize: IoLoc<Self::Target, u64>,
792        Self::Backend: IoCapable<u64>,
793    {
794        self.try_read(offset)
795    }
796
797    /// Fallible 8-bit write with runtime bounds check.
798    #[inline(always)]
799    fn try_write8(self, value: u8, offset: usize) -> Result
800    where
801        usize: IoLoc<Self::Target, u8>,
802        Self::Backend: IoCapable<u8>,
803    {
804        self.try_write(offset, value)
805    }
806
807    /// Fallible 16-bit write with runtime bounds check.
808    #[inline(always)]
809    fn try_write16(self, value: u16, offset: usize) -> Result
810    where
811        usize: IoLoc<Self::Target, u16>,
812        Self::Backend: IoCapable<u16>,
813    {
814        self.try_write(offset, value)
815    }
816
817    /// Fallible 32-bit write with runtime bounds check.
818    #[inline(always)]
819    fn try_write32(self, value: u32, offset: usize) -> Result
820    where
821        usize: IoLoc<Self::Target, u32>,
822        Self::Backend: IoCapable<u32>,
823    {
824        self.try_write(offset, value)
825    }
826
827    /// Fallible 64-bit write with runtime bounds check.
828    #[inline(always)]
829    fn try_write64(self, value: u64, offset: usize) -> Result
830    where
831        usize: IoLoc<Self::Target, u64>,
832        Self::Backend: IoCapable<u64>,
833    {
834        self.try_write(offset, value)
835    }
836
837    /// Infallible 8-bit read with compile-time bounds check.
838    ///
839    /// `offset` should be constant.
840    #[inline(always)]
841    fn read8(self, offset: usize) -> u8
842    where
843        usize: IoLoc<Self::Target, u8>,
844        Self::Backend: IoCapable<u8>,
845    {
846        self.read(offset)
847    }
848
849    /// Infallible 16-bit read with compile-time bounds check.
850    ///
851    /// `offset` should be constant.
852    #[inline(always)]
853    fn read16(self, offset: usize) -> u16
854    where
855        usize: IoLoc<Self::Target, u16>,
856        Self::Backend: IoCapable<u16>,
857    {
858        self.read(offset)
859    }
860
861    /// Infallible 32-bit read with compile-time bounds check.
862    ///
863    /// `offset` should be constant.
864    #[inline(always)]
865    fn read32(self, offset: usize) -> u32
866    where
867        usize: IoLoc<Self::Target, u32>,
868        Self::Backend: IoCapable<u32>,
869    {
870        self.read(offset)
871    }
872
873    /// Infallible 64-bit read with compile-time bounds check.
874    ///
875    /// `offset` should be constant.
876    #[inline(always)]
877    fn read64(self, offset: usize) -> u64
878    where
879        usize: IoLoc<Self::Target, u64>,
880        Self::Backend: IoCapable<u64>,
881    {
882        self.read(offset)
883    }
884
885    /// Infallible 8-bit write with compile-time bounds check.
886    ///
887    /// `offset` should be constant.
888    #[inline(always)]
889    fn write8(self, value: u8, offset: usize)
890    where
891        usize: IoLoc<Self::Target, u8>,
892        Self::Backend: IoCapable<u8>,
893    {
894        self.write(offset, value)
895    }
896
897    /// Infallible 16-bit write with compile-time bounds check.
898    ///
899    /// `offset` should be constant.
900    #[inline(always)]
901    fn write16(self, value: u16, offset: usize)
902    where
903        usize: IoLoc<Self::Target, u16>,
904        Self::Backend: IoCapable<u16>,
905    {
906        self.write(offset, value)
907    }
908
909    /// Infallible 32-bit write with compile-time bounds check.
910    ///
911    /// `offset` should be constant.
912    #[inline(always)]
913    fn write32(self, value: u32, offset: usize)
914    where
915        usize: IoLoc<Self::Target, u32>,
916        Self::Backend: IoCapable<u32>,
917    {
918        self.write(offset, value)
919    }
920
921    /// Infallible 64-bit write with compile-time bounds check.
922    ///
923    /// `offset` should be constant.
924    #[inline(always)]
925    fn write64(self, value: u64, offset: usize)
926    where
927        usize: IoLoc<Self::Target, u64>,
928        Self::Backend: IoCapable<u64>,
929    {
930        self.write(offset, value)
931    }
932
933    /// Generic fallible read with runtime bounds check.
934    ///
935    /// # Examples
936    ///
937    /// Read a primitive type from an I/O address:
938    ///
939    /// ```no_run
940    /// use kernel::io::{
941    ///     Io,
942    ///     Mmio,
943    ///     Region,
944    /// };
945    ///
946    /// fn do_reads(io: Mmio<'_, Region>) -> Result {
947    ///     // 32-bit read from address `0x10`.
948    ///     let v: u32 = io.try_read(0x10)?;
949    ///
950    ///     // 8-bit read from address `0xfff`.
951    ///     let v: u8 = io.try_read(0xfff)?;
952    ///
953    ///     Ok(())
954    /// }
955    /// ```
956    #[inline(always)]
957    fn try_read<T, L>(self, location: L) -> Result<T>
958    where
959        T: AsReprMut,
960        L: IoLoc<Self::Target, T>,
961        Self::Backend: IoCapable<<T as AsRepr>::Repr>,
962    {
963        Ok(io_read!(self, try: location))
964    }
965
966    /// Generic fallible write with runtime bounds check.
967    ///
968    /// # Examples
969    ///
970    /// Write a primitive type to an I/O address:
971    ///
972    /// ```no_run
973    /// use kernel::io::{
974    ///     Io,
975    ///     Mmio,
976    ///     Region,
977    /// };
978    ///
979    /// fn do_writes(io: Mmio<'_, Region>) -> Result {
980    ///     // 32-bit write of value `1` at address `0x10`.
981    ///     io.try_write(0x10, 1u32)?;
982    ///
983    ///     // 8-bit write of value `0xff` at address `0xfff`.
984    ///     io.try_write(0xfff, 0xffu8)?;
985    ///
986    ///     Ok(())
987    /// }
988    /// ```
989    #[inline(always)]
990    fn try_write<T, L>(self, location: L, value: T) -> Result
991    where
992        T: AsRepr,
993        L: IoLoc<Self::Target, T>,
994        Self::Backend: IoCapable<<T as AsRepr>::Repr>,
995    {
996        io_write!(self, try: location, value);
997        Ok(())
998    }
999
1000    /// Generic fallible write of a fully-located register value.
1001    ///
1002    /// # Examples
1003    ///
1004    /// Tuples carrying a location and a value can be used with this method:
1005    ///
1006    /// ```no_run
1007    /// use kernel::io::{
1008    ///     register,
1009    ///     Io,
1010    ///     Mmio,
1011    ///     Region,
1012    /// };
1013    ///
1014    /// register! {
1015    ///     base: Region;
1016    ///
1017    ///     VERSION(u32) @ 0x100 {
1018    ///         15:8 major;
1019    ///         7:0  minor;
1020    ///     }
1021    /// }
1022    ///
1023    /// impl VERSION {
1024    ///     fn new(major: u8, minor: u8) -> Self {
1025    ///         VERSION::zeroed().with_major(major).with_minor(minor)
1026    ///     }
1027    /// }
1028    ///
1029    /// fn do_write_reg(io: Mmio<'_, Region>) -> Result {
1030    ///
1031    ///     io.try_write_reg(VERSION::new(1, 0))
1032    /// }
1033    /// ```
1034    #[inline(always)]
1035    fn try_write_reg<T, L, V>(self, value: V) -> Result
1036    where
1037        T: AsRepr,
1038        L: IoLoc<Self::Target, T>,
1039        V: LocatedRegister<Self::Target, Location = L, Value = T>,
1040        Self::Backend: IoCapable<<T as AsRepr>::Repr>,
1041    {
1042        let (location, value) = value.into_io_op();
1043
1044        self.try_write(location, value)
1045    }
1046
1047    /// Generic fallible update with runtime bounds check.
1048    ///
1049    /// Note: this does not perform any synchronization. The caller is responsible for ensuring
1050    /// exclusive access if required.
1051    ///
1052    /// # Examples
1053    ///
1054    /// Read the u32 value at address `0x10`, increment it, and store the updated value back:
1055    ///
1056    /// ```no_run
1057    /// use kernel::io::{
1058    ///     Io,
1059    ///     Mmio,
1060    ///     Region,
1061    /// };
1062    ///
1063    /// fn do_update(io: Mmio<'_, Region<0x1000>>) -> Result {
1064    ///     io.try_update(0x10, |v: u32| {
1065    ///         v + 1
1066    ///     })
1067    /// }
1068    /// ```
1069    #[inline(always)]
1070    fn try_update<T, L, F>(self, location: L, f: F) -> Result
1071    where
1072        T: AsReprMut,
1073        L: IoLoc<Self::Target, T>,
1074        Self::Backend: IoCapable<<T as AsRepr>::Repr>,
1075        F: FnOnce(T) -> T,
1076    {
1077        let view = io_project!(self, try: location);
1078        view.write_val(f(view.read_val()));
1079        Ok(())
1080    }
1081
1082    /// Generic infallible read with compile-time bounds check.
1083    ///
1084    /// # Examples
1085    ///
1086    /// Read a primitive type from an I/O address:
1087    ///
1088    /// ```no_run
1089    /// use kernel::io::{
1090    ///     Io,
1091    ///     Mmio,
1092    ///     Region,
1093    /// };
1094    ///
1095    /// fn do_reads(io: Mmio<'_, Region<0x1000>>) {
1096    ///     // 32-bit read from address `0x10`.
1097    ///     let v: u32 = io.read(0x10);
1098    ///
1099    ///     // 8-bit read from the top of the I/O space.
1100    ///     let v: u8 = io.read(0xfff);
1101    /// }
1102    /// ```
1103    #[inline(always)]
1104    fn read<T, L>(self, location: L) -> T
1105    where
1106        T: AsReprMut,
1107        L: IoLoc<Self::Target, T>,
1108        Self::Backend: IoCapable<<T as AsRepr>::Repr>,
1109    {
1110        io_read!(self, build: location)
1111    }
1112
1113    /// Generic infallible write with compile-time bounds check.
1114    ///
1115    /// # Examples
1116    ///
1117    /// Write a primitive type to an I/O address:
1118    ///
1119    /// ```no_run
1120    /// use kernel::io::{
1121    ///     Io,
1122    ///     Mmio,
1123    ///     Region,
1124    /// };
1125    ///
1126    /// fn do_writes(io: Mmio<'_, Region<0x1000>>) {
1127    ///     // 32-bit write of value `1` at address `0x10`.
1128    ///     io.write(0x10, 1u32);
1129    ///
1130    ///     // 8-bit write of value `0xff` at the top of the I/O space.
1131    ///     io.write(0xfff, 0xffu8);
1132    /// }
1133    /// ```
1134    #[inline(always)]
1135    fn write<T, L>(self, location: L, value: T)
1136    where
1137        T: AsRepr,
1138        L: IoLoc<Self::Target, T>,
1139        Self::Backend: IoCapable<<T as AsRepr>::Repr>,
1140    {
1141        io_write!(self, build: location, value);
1142    }
1143
1144    /// Generic infallible write of a fully-located register value.
1145    ///
1146    /// # Examples
1147    ///
1148    /// Tuples carrying a location and a value can be used with this method:
1149    ///
1150    /// ```no_run
1151    /// use kernel::io::{
1152    ///     register,
1153    ///     Io,
1154    ///     Mmio,
1155    ///     Region,
1156    /// };
1157    ///
1158    /// register! {
1159    ///     base: Region<0x1000>;
1160    ///
1161    ///     VERSION(u32) @ 0x100 {
1162    ///         15:8 major;
1163    ///         7:0  minor;
1164    ///     }
1165    /// }
1166    ///
1167    /// impl VERSION {
1168    ///     fn new(major: u8, minor: u8) -> Self {
1169    ///         VERSION::zeroed().with_major(major).with_minor(minor)
1170    ///     }
1171    /// }
1172    ///
1173    /// fn do_write_reg(io: Mmio<'_, Region<0x1000>>) {
1174    ///     io.write_reg(VERSION::new(1, 0));
1175    /// }
1176    /// ```
1177    #[inline(always)]
1178    fn write_reg<T, L, V>(self, value: V)
1179    where
1180        T: AsRepr,
1181        L: IoLoc<Self::Target, T>,
1182        V: LocatedRegister<Self::Target, Location = L, Value = T>,
1183        Self::Backend: IoCapable<<T as AsRepr>::Repr>,
1184    {
1185        let (location, value) = value.into_io_op();
1186
1187        self.write(location, value)
1188    }
1189
1190    /// Generic infallible update with compile-time bounds check.
1191    ///
1192    /// Note: this does not perform any synchronization. The caller is responsible for ensuring
1193    /// exclusive access if required.
1194    ///
1195    /// # Examples
1196    ///
1197    /// Read the u32 value at address `0x10`, increment it, and store the updated value back:
1198    ///
1199    /// ```no_run
1200    /// use kernel::io::{
1201    ///     Io,
1202    ///     Mmio,
1203    ///     Region,
1204    /// };
1205    ///
1206    /// fn do_update(io: Mmio<'_, Region<0x1000>>) {
1207    ///     io.update(0x10, |v: u32| {
1208    ///         v + 1
1209    ///     })
1210    /// }
1211    /// ```
1212    #[inline(always)]
1213    fn update<T, L, F>(self, location: L, f: F)
1214    where
1215        T: AsReprMut,
1216        L: IoLoc<Self::Target, T>,
1217        Self::Backend: IoCapable<<T as AsRepr>::Repr>,
1218        F: FnOnce(T) -> T,
1219    {
1220        let view = io_project!(self, build: location);
1221        view.write_val(f(view.read_val()));
1222    }
1223}
1224
1225// Blanket implementation ensures that provided methods cannot be arbitrarily overridden by
1226// implementers, which is relied upon for correctness and soundness.
1227impl<'a, T: IoBase<'a>> Io<'a> for T {}
1228
1229/// A view of memory-mapped I/O region.
1230///
1231/// # Invariant
1232///
1233/// `ptr` points to a valid and aligned memory-mapped I/O region for the duration lifetime `'a`.
1234pub struct Mmio<'a, T: ?Sized> {
1235    ptr: *mut T,
1236    phantom: PhantomData<&'a ()>,
1237}
1238
1239impl<T: ?Sized> Copy for Mmio<'_, T> {}
1240impl<T: ?Sized> Clone for Mmio<'_, T> {
1241    #[inline]
1242    fn clone(&self) -> Self {
1243        *self
1244    }
1245}
1246
1247impl<'a, T: ?Sized> Mmio<'a, T> {
1248    /// Create a `Mmio`, providing the accessors to the MMIO mapping.
1249    ///
1250    /// # Safety
1251    ///
1252    /// `raw` represents a valid and aligned memory-mapped I/O region while `'a` is alive.
1253    #[inline]
1254    pub unsafe fn from_raw(raw: MmioRaw<T>) -> Self {
1255        // INVARIANT: Per safety requirement.
1256        Self {
1257            ptr: raw.ptr,
1258            phantom: PhantomData,
1259        }
1260    }
1261}
1262
1263// SAFETY: `Mmio<'_, T>` is conceptually `&T` but in I/O memory.
1264unsafe impl<T: ?Sized + Sync> Send for Mmio<'_, T> {}
1265
1266// SAFETY: `Mmio<'_, T>` is conceptually `&T` but in I/O memory.
1267unsafe impl<T: ?Sized + Sync> Sync for Mmio<'_, T> {}
1268
1269impl<'a, T: ?Sized + KnownSize> IoBase<'a> for Mmio<'a, T> {
1270    type Backend = MmioBackend;
1271    type Target = T;
1272
1273    #[inline]
1274    fn as_view(self) -> Mmio<'a, T> {
1275        self
1276    }
1277}
1278
1279/// I/O Backend for memory-mapped I/O.
1280pub struct MmioBackend;
1281
1282impl IoBackend for MmioBackend {
1283    type View<'a, T: ?Sized + KnownSize> = Mmio<'a, T>;
1284
1285    #[inline]
1286    fn as_ptr<'a, T: ?Sized + KnownSize>(view: Self::View<'a, T>) -> *mut T {
1287        view.ptr
1288    }
1289
1290    #[inline]
1291    unsafe fn project_view<'a, T: ?Sized + KnownSize, U: ?Sized + KnownSize>(
1292        _view: Self::View<'a, T>,
1293        ptr: *mut U,
1294    ) -> Self::View<'a, U> {
1295        // INVARIANT: Per safety requirement, `ptr` is projection from `view`, so it is also a valid
1296        // memory-mapped I/O region.
1297        Mmio {
1298            ptr,
1299            phantom: PhantomData,
1300        }
1301    }
1302}
1303
1304/// Implements [`IoCapable`] on `$backend` for `$ty` using `$read_fn` and `$write_fn`.
1305macro_rules! impl_mmio_io_capable {
1306    ($backend: ident, $ty:ty, $read_fn:ident, $write_fn:ident) => {
1307        impl IoCapable<$ty> for $backend {
1308            #[inline]
1309            fn io_read(view: <$backend as IoBackend>::View<'_, $ty>) -> $ty {
1310                // SAFETY: `$backend::as_ptr(view)` is a valid pointer for MMIO operations for both
1311                // `MmioBackend` and `RelaxedMmioBackend`.
1312                unsafe { bindings::$read_fn($backend::as_ptr(view).cast_const().cast()) }
1313            }
1314
1315            #[inline]
1316            fn io_write(view: <$backend as IoBackend>::View<'_, $ty>, value: $ty) {
1317                // SAFETY: `$backend::as_ptr(view)` is a valid pointer for MMIO operations for both
1318                // `MmioBackend` and `RelaxedMmioBackend`.
1319                unsafe { bindings::$write_fn(value, $backend::as_ptr(view).cast()) }
1320            }
1321        }
1322    };
1323}
1324
1325// MMIO regions support 8, 16, and 32-bit accesses.
1326impl_mmio_io_capable!(MmioBackend, u8, readb, writeb);
1327impl_mmio_io_capable!(MmioBackend, u16, readw, writew);
1328impl_mmio_io_capable!(MmioBackend, u32, readl, writel);
1329// MMIO regions on 64-bit systems also support 64-bit accesses.
1330#[cfg(CONFIG_64BIT)]
1331impl_mmio_io_capable!(MmioBackend, u64, readq, writeq);
1332
1333impl IoCopyable for MmioBackend {
1334    #[inline]
1335    unsafe fn copy_from_io(view: Self::View<'_, [u8]>, buffer: *mut u8) {
1336        // SAFETY:
1337        // - `view.ptr` is valid MMIO memory for `view.size()` bytes.
1338        // - `buffer` is valid for write for `view.size()` bytes.
1339        unsafe {
1340            bindings::memcpy_fromio(buffer.cast(), view.ptr.cast(), view.size());
1341        }
1342    }
1343
1344    #[inline]
1345    unsafe fn copy_to_io(view: Self::View<'_, [u8]>, buffer: *const u8) {
1346        // SAFETY:
1347        // - `view.ptr` is valid MMIO memory for `view.size()` bytes.
1348        // - `buffer` is valid for read for `view.size()` bytes.
1349        unsafe {
1350            bindings::memcpy_toio(view.ptr.cast(), buffer.cast(), view.size());
1351        }
1352    }
1353}
1354
1355/// [`Mmio`] but using relaxed accessors.
1356///
1357/// This type provides an implementation of [`Io`] that uses relaxed I/O MMIO operands instead of
1358/// the regular ones.
1359///
1360/// See [`Mmio::relaxed`] for a usage example.
1361pub struct RelaxedMmio<'a, T: ?Sized>(Mmio<'a, T>);
1362
1363impl<T: ?Sized> Copy for RelaxedMmio<'_, T> {}
1364impl<T: ?Sized> Clone for RelaxedMmio<'_, T> {
1365    #[inline]
1366    fn clone(&self) -> Self {
1367        *self
1368    }
1369}
1370
1371/// I/O Backend for memory-mapped I/O, with relaxed access semantics.
1372pub struct RelaxedMmioBackend;
1373
1374impl IoBackend for RelaxedMmioBackend {
1375    type View<'a, T: ?Sized + KnownSize> = RelaxedMmio<'a, T>;
1376
1377    #[inline]
1378    fn as_ptr<'a, T: ?Sized + KnownSize>(view: Self::View<'a, T>) -> *mut T {
1379        MmioBackend::as_ptr(view.0)
1380    }
1381
1382    #[inline]
1383    unsafe fn project_view<'a, T: ?Sized + KnownSize, U: ?Sized + KnownSize>(
1384        view: Self::View<'a, T>,
1385        ptr: *mut U,
1386    ) -> Self::View<'a, U> {
1387        // SAFETY: Per safety requirement.
1388        RelaxedMmio(unsafe { MmioBackend::project_view(view.0, ptr) })
1389    }
1390}
1391
1392impl<'a, T: ?Sized + KnownSize> IoBase<'a> for RelaxedMmio<'a, T> {
1393    type Backend = RelaxedMmioBackend;
1394    type Target = T;
1395
1396    #[inline]
1397    fn as_view(self) -> RelaxedMmio<'a, T> {
1398        self
1399    }
1400}
1401
1402impl<'a, T: ?Sized> Mmio<'a, T> {
1403    /// Returns a [`RelaxedMmio`] that performs relaxed I/O operations.
1404    ///
1405    /// Relaxed accessors do not provide ordering guarantees with respect to DMA or memory accesses
1406    /// and can be used when such ordering is not required.
1407    ///
1408    /// # Examples
1409    ///
1410    /// ```no_run
1411    /// use kernel::io::{
1412    ///     Io,
1413    ///     Mmio,
1414    ///     Region,
1415    ///     RelaxedMmio,
1416    /// };
1417    ///
1418    /// fn do_io(io: Mmio<'_, Region<0x100>>) {
1419    ///     // The access is performed using `readl_relaxed` instead of `readl`.
1420    ///     let v = io.relaxed().read32(0x10);
1421    /// }
1422    ///
1423    /// ```
1424    #[inline]
1425    pub fn relaxed(self) -> RelaxedMmio<'a, T> {
1426        RelaxedMmio(self)
1427    }
1428}
1429
1430// MMIO regions support 8, 16, and 32-bit accesses.
1431impl_mmio_io_capable!(RelaxedMmioBackend, u8, readb_relaxed, writeb_relaxed);
1432impl_mmio_io_capable!(RelaxedMmioBackend, u16, readw_relaxed, writew_relaxed);
1433impl_mmio_io_capable!(RelaxedMmioBackend, u32, readl_relaxed, writel_relaxed);
1434// MMIO regions on 64-bit systems also support 64-bit accesses.
1435#[cfg(CONFIG_64BIT)]
1436impl_mmio_io_capable!(RelaxedMmioBackend, u64, readq_relaxed, writeq_relaxed);
1437
1438/// I/O Backend for system memory.
1439pub struct SysMemBackend;
1440
1441impl IoBackend for SysMemBackend {
1442    type View<'a, T: ?Sized + KnownSize> = SysMem<'a, T>;
1443
1444    #[inline]
1445    fn as_ptr<'a, T: ?Sized + KnownSize>(view: Self::View<'a, T>) -> *mut T {
1446        view.ptr
1447    }
1448
1449    #[inline]
1450    unsafe fn project_view<'a, T: ?Sized + KnownSize, U: ?Sized + KnownSize>(
1451        _view: Self::View<'a, T>,
1452        ptr: *mut U,
1453    ) -> Self::View<'a, U> {
1454        // INVARIANT: Per safety requirement, `ptr` is projection from `view`, so it is also a valid
1455        // kernel accessible memory region.
1456        SysMem {
1457            ptr,
1458            phantom: PhantomData,
1459        }
1460    }
1461}
1462
1463/// Implements [`IoCapable`] on `SysMemBackend` for `$ty` using `read_volatile` and
1464/// `write_volatile`.
1465macro_rules! impl_sysmem_io_capable {
1466    ($ty:ty) => {
1467        impl IoCapable<$ty> for SysMemBackend {
1468            #[inline]
1469            fn io_read(view: SysMem<'_, $ty>) -> $ty {
1470                // SAFETY:
1471                // - Per type invariant, `ptr` is valid and aligned.
1472                // - Using read_volatile() here so that race with hardware is well-defined.
1473                // - Using read_volatile() here is not sound if it races with other CPU per Rust
1474                //   rules, but this is allowed per LKMM.
1475                // - The macro is only used on primitives so all bit patterns are valid.
1476                unsafe { view.ptr.read_volatile() }
1477            }
1478
1479            #[inline]
1480            fn io_write(view: SysMem<'_, $ty>, value: $ty) {
1481                // SAFETY:
1482                // - Per type invariant, `ptr` is valid and aligned.
1483                // - Using write_volatile() here so that race with hardware is well-defined.
1484                // - Using write_volatile() here is not sound if it races with other CPU per Rust
1485                //   rules, but this is allowed per LKMM.
1486                unsafe { view.ptr.write_volatile(value) }
1487            }
1488        }
1489    };
1490}
1491
1492impl_sysmem_io_capable!(u8);
1493impl_sysmem_io_capable!(u16);
1494impl_sysmem_io_capable!(u32);
1495#[cfg(CONFIG_64BIT)]
1496impl_sysmem_io_capable!(u64);
1497
1498impl IoCopyable for SysMemBackend {
1499    #[inline]
1500    unsafe fn copy_from_io(view: Self::View<'_, [u8]>, buffer: *mut u8) {
1501        // Use `bindings::memcpy` instead of `copy_nonoverlapping` for volatile.
1502        // SAFETY:
1503        // - `view.ptr` is in CPU address space and valid for read.
1504        // - `buffer` is valid for write for `view.size()` bytes which is equal to `view.ptr.len()`.
1505        unsafe { bindings::memcpy(buffer.cast(), view.ptr.cast(), view.ptr.len()) };
1506    }
1507
1508    #[inline]
1509    unsafe fn copy_to_io(view: Self::View<'_, [u8]>, buffer: *const u8) {
1510        // Use `bindings::memcpy` instead of `copy_nonoverlapping` for volatile.
1511        // SAFETY:
1512        // - `view.ptr` is in CPU address space and valid for write.
1513        // - `buffer` is valid for read for `view.size()` bytes which is equal to `view.ptr.len()`.
1514        unsafe { bindings::memcpy(view.ptr.cast(), buffer.cast(), view.ptr.len()) };
1515    }
1516
1517    #[inline]
1518    fn copy_read<T: FromBytes>(view: Self::View<'_, T>) -> T {
1519        // SAFETY:
1520        // - Per type invariant, `ptr` is valid and aligned.
1521        // - Using read_volatile() here so that race with hardware is well-defined.
1522        // - Using read_volatile() here is not sound if it races with other CPU per Rust
1523        //   rules, but this is allowed per LKMM.
1524        // - `T: FromBytes` so all bit patterns are valid.
1525        unsafe { view.ptr.read_volatile() }
1526    }
1527
1528    #[inline]
1529    fn copy_write<T: IntoBytes>(view: Self::View<'_, T>, value: T) {
1530        // SAFETY:
1531        // - Per type invariant, `ptr` is valid and aligned.
1532        // - Using write_volatile() here so that race with hardware is well-defined.
1533        // - Using write_volatile() here is not sound if it races with other CPU per Rust
1534        //   rules, but this is allowed per LKMM.
1535        unsafe { view.ptr.write_volatile(value) }
1536    }
1537}
1538
1539/// A view of a system memory region.
1540///
1541/// Provides `Io` trait implementation for kernel virtual address ranges,
1542/// using volatile read/write to safely access shared memory that may be
1543/// concurrently accessed by external hardware.
1544///
1545/// # Invariants
1546///
1547/// `self.ptr.addr() .. self.ptr.addr() + KnownSize::size(self.ptr)` is valid and aligned kernel
1548/// accessible memory region for the lifetime `'a`.
1549pub struct SysMem<'a, T: ?Sized> {
1550    ptr: *mut T,
1551    phantom: PhantomData<&'a ()>,
1552}
1553
1554impl<T: ?Sized> Copy for SysMem<'_, T> {}
1555impl<T: ?Sized> Clone for SysMem<'_, T> {
1556    #[inline]
1557    fn clone(&self) -> Self {
1558        *self
1559    }
1560}
1561
1562// SAFETY: `SysMem<'_, T>` is conceptually `&T`.
1563unsafe impl<T: ?Sized + Sync> Send for SysMem<'_, T> {}
1564
1565// SAFETY: `SysMem<'_, T>` is conceptually `&T`.
1566unsafe impl<T: ?Sized + Sync> Sync for SysMem<'_, T> {}
1567
1568impl<'a, T: ?Sized> SysMem<'a, T> {
1569    /// Create a `SysMem` from a raw pointer.
1570    ///
1571    /// # Safety
1572    ///
1573    /// `ptr.addr() .. ptr.addr() + KnownSize::size(ptr)` must be valid and aligned kernel
1574    /// accessible memory region for the lifetime `'a`.
1575    #[inline]
1576    pub unsafe fn new(ptr: *mut T) -> Self {
1577        // INVARIANT: Per safety requirement.
1578        Self {
1579            ptr,
1580            phantom: PhantomData,
1581        }
1582    }
1583
1584    /// Obtain the raw pointer to the memory.
1585    #[inline]
1586    pub fn as_ptr(self) -> *mut T {
1587        self.ptr
1588    }
1589}
1590
1591impl<'a, T: ?Sized + KnownSize> IoBase<'a> for SysMem<'a, T> {
1592    type Backend = SysMemBackend;
1593    type Target = T;
1594
1595    #[inline]
1596    fn as_view(self) -> <Self::Backend as IoBackend>::View<'a, Self::Target> {
1597        self
1598    }
1599}
1600
1601/// I/O Backend for [`IoSysMap`].
1602pub struct IoSysMapBackend;
1603
1604/// Either [`Mmio`] or [`SysMem`].
1605///
1606/// This can be used when a piece of logic may wish to handle both MMIO or system memory but does
1607/// not want or cannot be generic over I/O backends. This serves a similar purpose to
1608/// [`include/linux/iosys-map.h`] in C.
1609///
1610/// This type can be used like any other types that implements [`Io`]; this also include
1611/// [`io_project!`], [`io_read!`], [`io_write!`].
1612///
1613/// [`include/linux/iosys-map.h`]: srctree/include/linux/iosys-map.h
1614pub enum IoSysMap<'a, T: ?Sized> {
1615    /// The view is I/O memory.
1616    Io(Mmio<'a, T>),
1617    /// The view is system memory.
1618    Sys(SysMem<'a, T>),
1619}
1620
1621impl<T: ?Sized> Copy for IoSysMap<'_, T> {}
1622impl<T: ?Sized> Clone for IoSysMap<'_, T> {
1623    #[inline]
1624    fn clone(&self) -> Self {
1625        *self
1626    }
1627}
1628
1629impl<'a, T: ?Sized> From<Mmio<'a, T>> for IoSysMap<'a, T> {
1630    #[inline]
1631    fn from(value: Mmio<'a, T>) -> Self {
1632        IoSysMap::Io(value)
1633    }
1634}
1635
1636impl<'a, T: ?Sized> From<SysMem<'a, T>> for IoSysMap<'a, T> {
1637    #[inline]
1638    fn from(value: SysMem<'a, T>) -> Self {
1639        IoSysMap::Sys(value)
1640    }
1641}
1642
1643impl IoBackend for IoSysMapBackend {
1644    type View<'a, T: ?Sized + KnownSize> = IoSysMap<'a, T>;
1645
1646    #[inline]
1647    fn as_ptr<'a, T: ?Sized + KnownSize>(view: Self::View<'a, T>) -> *mut T {
1648        match view {
1649            IoSysMap::Io(l) => MmioBackend::as_ptr(l),
1650            IoSysMap::Sys(r) => SysMemBackend::as_ptr(r),
1651        }
1652    }
1653
1654    #[inline]
1655    unsafe fn project_view<'a, T: ?Sized + KnownSize, U: ?Sized + KnownSize>(
1656        view: Self::View<'a, T>,
1657        ptr: *mut U,
1658    ) -> Self::View<'a, U> {
1659        match view {
1660            // SAFETY: Per safety requirement.
1661            IoSysMap::Io(l) => IoSysMap::Io(unsafe { MmioBackend::project_view(l, ptr) }),
1662            // SAFETY: Per safety requirement.
1663            IoSysMap::Sys(r) => IoSysMap::Sys(unsafe { SysMemBackend::project_view(r, ptr) }),
1664        }
1665    }
1666}
1667
1668impl<T> IoCapable<T> for IoSysMapBackend
1669where
1670    MmioBackend: IoCapable<T>,
1671    SysMemBackend: IoCapable<T>,
1672{
1673    #[inline]
1674    fn io_read(view: Self::View<'_, T>) -> T {
1675        match view {
1676            IoSysMap::Io(l) => MmioBackend::io_read(l),
1677            IoSysMap::Sys(r) => SysMemBackend::io_read(r),
1678        }
1679    }
1680
1681    #[inline]
1682    fn io_write<'a>(view: Self::View<'a, T>, value: T) {
1683        match view {
1684            IoSysMap::Io(l) => MmioBackend::io_write(l, value),
1685            IoSysMap::Sys(r) => SysMemBackend::io_write(r, value),
1686        }
1687    }
1688}
1689
1690impl IoCopyable for IoSysMapBackend {
1691    #[inline]
1692    unsafe fn copy_from_io(view: Self::View<'_, [u8]>, buffer: *mut u8) {
1693        match view {
1694            // SAFETY: Per safety requirement.
1695            IoSysMap::Io(l) => unsafe { MmioBackend::copy_from_io(l, buffer) },
1696            // SAFETY: Per safety requirement.
1697            IoSysMap::Sys(r) => unsafe { SysMemBackend::copy_from_io(r, buffer) },
1698        }
1699    }
1700
1701    #[inline]
1702    unsafe fn copy_to_io(view: Self::View<'_, [u8]>, buffer: *const u8) {
1703        match view {
1704            // SAFETY: Per safety requirement.
1705            IoSysMap::Io(l) => unsafe { MmioBackend::copy_to_io(l, buffer) },
1706            // SAFETY: Per safety requirement.
1707            IoSysMap::Sys(r) => unsafe { SysMemBackend::copy_to_io(r, buffer) },
1708        }
1709    }
1710
1711    #[inline]
1712    fn copy_read<T: FromBytes>(view: Self::View<'_, T>) -> T {
1713        match view {
1714            IoSysMap::Io(l) => MmioBackend::copy_read(l),
1715            IoSysMap::Sys(r) => SysMemBackend::copy_read(r),
1716        }
1717    }
1718
1719    #[inline]
1720    fn copy_write<T: IntoBytes>(view: Self::View<'_, T>, value: T) {
1721        match view {
1722            IoSysMap::Io(l) => MmioBackend::copy_write(l, value),
1723            IoSysMap::Sys(r) => SysMemBackend::copy_write(r, value),
1724        }
1725    }
1726}
1727
1728impl<'a, T: ?Sized + KnownSize> IoBase<'a> for IoSysMap<'a, T> {
1729    type Backend = IoSysMapBackend;
1730    type Target = T;
1731
1732    #[inline]
1733    fn as_view(self) -> IoSysMap<'a, T> {
1734        self
1735    }
1736}
1737
1738// This helper turns associated functions to methods so it can be invoked in macro.
1739// Used by `io_project!()` only.
1740#[doc(hidden)]
1741#[derive(Clone, Copy)]
1742pub struct ProjectHelper<T>(pub T);
1743
1744impl<'a, T> ProjectHelper<T>
1745where
1746    T: Io<'a, Backend: IoBackend<View<'a, T::Target> = T>>,
1747{
1748    // These helper methods must not have symbols present in the binary to avoid confusion.
1749    #[inline(always)]
1750    pub fn as_ptr(self) -> *mut T::Target {
1751        T::Backend::as_ptr(self.0)
1752    }
1753
1754    /// # Safety
1755    ///
1756    /// Same as `IoBackend::project_view`
1757    #[inline(always)]
1758    pub unsafe fn project_view<U: ?Sized + KnownSize>(
1759        self,
1760        ptr: *mut U,
1761    ) -> <T::Backend as IoBackend>::View<'a, U> {
1762        // SAFETY: Per safety requirement.
1763        unsafe { T::Backend::project_view::<T::Target, _>(self.0, ptr) }
1764    }
1765
1766    #[inline(always)]
1767    pub fn try_project_loc<U, L>(
1768        self,
1769        location: L,
1770    ) -> Result<<T::Backend as IoBackend>::View<'a, U>>
1771    where
1772        L: IoLoc<T::Target, U>,
1773    {
1774        io_view::<_, U>(self.0, location.offset())
1775    }
1776
1777    #[inline(always)]
1778    pub fn project_loc<U, L>(self, location: L) -> <T::Backend as IoBackend>::View<'a, U>
1779    where
1780        L: IoLoc<T::Target, U>,
1781    {
1782        io_view_assert::<_, U>(self.0, location.offset())
1783    }
1784}
1785
1786/// Project an I/O type to a subview of it.
1787///
1788/// The syntax is of form `io_project!(io, proj)` where `io` is an expression to a type that
1789/// implements [`Io`] and `proj` is a [projection specification](kernel::ptr::project!).
1790///
1791/// `io_project!` can also project to a subview of registers defined with [`register!`] macro.
1792/// Register projection has syntax `io_project!(io, try: REGISTER)` for fallible projection and
1793/// `io_project!(io, build: REGISTER)` for infallible projection.
1794///
1795/// # Examples
1796///
1797/// ```
1798/// use kernel::io::{
1799///     io_project,
1800///     register,
1801///     Mmio,
1802/// };
1803/// #[repr(C)]
1804/// struct MyStruct { field: u32, }
1805///
1806/// register! {
1807///     base: MyStruct;
1808///     FIELD(u32) @ 0 {
1809///         31:0 val;
1810///     }
1811/// }
1812///
1813/// # fn test(mmio: Mmio<'_, [MyStruct]>) -> Result {
1814/// // let mmio: Mmio<[MyStruct]>;
1815/// let field: Mmio<'_, u32> = io_project!(mmio, [try: 1].field);
1816/// let whole: Mmio<'_, MyStruct> = io_project!(mmio, [try: 2]);
1817/// let nested: Mmio<'_, u32> = io_project!(whole, .field);
1818/// let reg: Mmio<'_, FIELD> = io_project!(whole, build: FIELD);
1819/// # Ok::<(), Error>(()) }
1820/// ```
1821#[macro_export]
1822#[doc(hidden)]
1823macro_rules! io_project {
1824    // Register projection
1825    ($io:expr, try: $ioloc:expr) => {{
1826        #[allow(unused)]
1827        use $crate::io::IoBase as _;
1828        let view = $crate::io::ProjectHelper($io.as_view());
1829        view.try_project_loc($ioloc)?
1830    }};
1831    ($io:expr, build: $ioloc:expr) => {{
1832        #[allow(unused)]
1833        use $crate::io::IoBase as _;
1834        let view = $crate::io::ProjectHelper($io.as_view());
1835        view.project_loc($ioloc)
1836    }};
1837
1838    // Field or index projection
1839    ($io:expr, $($proj:tt)*) => {{
1840        #[allow(unused)]
1841        use $crate::io::IoBase as _;
1842        let view = $crate::io::ProjectHelper($io.as_view());
1843        let ptr = $crate::ptr::project!(
1844            mut view.as_ptr(), $($proj)*
1845        );
1846        #[allow(unused_unsafe)]
1847        // SAFETY: `ptr` is a projection.
1848        unsafe { view.project_view(ptr) }
1849    }};
1850}
1851#[doc(inline)]
1852pub use crate::io_project;
1853
1854/// Read from I/O memory.
1855///
1856/// The syntax is of form `io_read!(io, proj)` where `io` is an expression to a type that
1857/// implements [`Io`] and `proj` is a [projection specification](kernel::ptr::project!).
1858///
1859/// # Examples
1860///
1861/// ```
1862/// #[repr(C)]
1863/// struct MyStruct { field: u32, }
1864///
1865/// # fn test(mmio: kernel::io::Mmio<'_, [MyStruct]>) -> Result {
1866/// // let mmio: Mmio<'_, [MyStruct]>;
1867/// let field: u32 = kernel::io::io_read!(mmio, [try: 2].field);
1868/// # Ok::<(), Error>(()) }
1869/// ```
1870#[macro_export]
1871#[doc(hidden)]
1872macro_rules! io_read {
1873    ($io:expr, $($proj:tt)*) => {
1874        $crate::io::Io::read_val($crate::io_project!($io, $($proj)*))
1875    };
1876}
1877#[doc(inline)]
1878pub use crate::io_read;
1879
1880/// Writes to I/O memory.
1881///
1882/// The syntax is of form `io_write!(io, proj, val)` where `io` is an expression to a type that
1883/// implements [`Io`] and `proj` is a [projection specification](kernel::ptr::project!),
1884/// and `val` is the value to be written to the projected location.
1885///
1886/// # Examples
1887///
1888/// ```
1889/// #[repr(C)]
1890/// struct MyStruct { field: u32, }
1891///
1892/// # fn test(mmio: kernel::io::Mmio<'_, [MyStruct]>) -> Result {
1893/// // let mmio: Mmio<'_, [MyStruct]>;
1894/// kernel::io::io_write!(mmio, [try: 2].field, 10);
1895/// # Ok::<(), Error>(()) }
1896/// ```
1897#[macro_export]
1898#[doc(hidden)]
1899macro_rules! io_write {
1900    (@parse [$io:expr] [$($proj:tt)*] [, $val:expr]) => {
1901        $crate::io::Io::write_val($crate::io_project!($io, $($proj)*), $val)
1902    };
1903    (@parse [$io:expr] [$($proj:tt)*] [.$field:tt $($rest:tt)*]) => {
1904        $crate::io_write!(@parse [$io] [$($proj)* .$field] [$($rest)*])
1905    };
1906    (@parse [$io:expr] [$($proj:tt)*] [[$flavor:ident: $index:expr] $($rest:tt)*]) => {
1907        $crate::io_write!(@parse [$io] [$($proj)* [$flavor: $index]] [$($rest)*])
1908    };
1909    (@parse [$io:expr] [] [try: $ioloc:expr, $($rest:tt)*]) => {
1910        $crate::io_write!(@parse [$io] [try: $ioloc] [, $($rest)*])
1911    };
1912    (@parse [$io:expr] [] [build: $ioloc:expr, $($rest:tt)*]) => {
1913        $crate::io_write!(@parse [$io] [build: $ioloc] [, $($rest)*])
1914    };
1915    ($io:expr, $($rest:tt)*) => {
1916        $crate::io_write!(@parse [$io] [] [$($rest)*])
1917    };
1918}
1919#[doc(inline)]
1920pub use crate::io_write;