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