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