Re: [PATCH 2/8] rust: io: generalize `Mmio` to arbitrary type

Andreas Hindborg
2026-03-26T18:24:01Z

"Gary Guo" <gary@garyguo.net> writes:

> On Thu Mar 26, 2026 at 1:04 PM GMT, Andreas Hindborg wrote:
>> "Gary Guo" <gary@kernel.org> writes:
>>
>>> From: Gary Guo <gary@garyguo.net>
>>>
>>> Currently, `io::Mmio` always represent an untyped region of a compile-time
>>> known minimum size, which is roughly equivalent to `void __iomem*` (but
>>> with bound checks). However, it is useful to also be to represent I/O
>>> memory of a specific type, e.g. `u32 __iomem*` or `struct foo __iomem*`.
>>>
>>> Thus, make `Mmio` generic on arbitrary `T`, where `T` is a sized type, or a
>>> DST that implements `KnownSize`. Similar to the `MmioRaw` change, the
>>> existing behaviour is preserved in the form of `Mmio<Region<SIZE>>`. This
>>> change brings the MMIO closer to the DMA coherent allocation types that we
>>> have, which is already typed.
>>>
>>> To be able to implement `IoKnownSize`, add a `MIN_SIZE` constant to
>>> `KnownSize` trait to represent compile-time known minimum size of a
>>> specific type.
>>>
>>> Signed-off-by: Gary Guo <gary@garyguo.net>
>>> ---
>>> rust/kernel/devres.rs | 2 +-
>>> rust/kernel/io.rs | 63 ++++++++++++++++++++++----------------
>>> rust/kernel/io/mem.rs | 4 +--
>>> rust/kernel/io/poll.rs | 6 ++--
>>> rust/kernel/io/register.rs | 19 +++++++-----
>>> rust/kernel/pci/io.rs | 2 +-
>>> rust/kernel/ptr.rs | 7 +++++
>>> 7 files changed, 64 insertions(+), 39 deletions(-)
>>>
>>> diff --git a/rust/kernel/devres.rs b/rust/kernel/devres.rs
>>> index 65a4082122af..3e22c63efb98 100644
>>> --- a/rust/kernel/devres.rs
>>> +++ b/rust/kernel/devres.rs
>>> @@ -106,7 +106,7 @@ struct Inner<T> {
>>> /// }
>>> ///
>>> /// impl<const SIZE: usize> Deref for IoMem<SIZE> {
>>> -/// type Target = Mmio<SIZE>;
>>> +/// type Target = Mmio<Region<SIZE>>;
>>> ///
>>> /// fn deref(&self) -> &Self::Target {
>>> /// // SAFETY: The memory range stored in `self` has been properly mapped in `Self::new`.
>>> diff --git a/rust/kernel/io.rs b/rust/kernel/io.rs
>>> index d7f2145fa9b9..5a26b1e7e533 100644
>>> --- a/rust/kernel/io.rs
>>> +++ b/rust/kernel/io.rs
>>> @@ -44,6 +44,8 @@ pub struct Region<const SIZE: usize = 0> {
>>> }
>>>
>>> impl<const SIZE: usize> KnownSize for Region<SIZE> {
>>> + const MIN_SIZE: usize = SIZE;
>>> +
>>> #[inline(always)]
>>> fn size(p: *const Self) -> usize {
>>> (p as *const [u8]).len()
>>> @@ -169,7 +171,7 @@ pub fn size(&self) -> usize {
>>> /// }
>>> ///
>>> /// impl<const SIZE: usize> Deref for IoMem<SIZE> {
>>> -/// type Target = Mmio<SIZE>;
>>> +/// type Target = Mmio<Region<SIZE>>;
>>> ///
>>> /// fn deref(&self) -> &Self::Target {
>>> /// // SAFETY: The memory range stored in `self` has been properly mapped in `Self::new`.
>>> @@ -187,7 +189,7 @@ pub fn size(&self) -> usize {
>>> /// # }
>>> /// ```
>>> #[repr(transparent)]
>>> -pub struct Mmio<const SIZE: usize = 0>(MmioRaw<Region<SIZE>>);
>>> +pub struct Mmio<T: ?Sized>(MmioRaw<T>);
>>
>> Why not have the `KnownSize` bound here? I think that would be more clear.
>>
>
> There's no need to put bounds on structs unless you need them for `Drop` or use
> of assoc types.

I understand there is no technical need, but it would help communicating
how the code is intended to work. Unless I am mistaken, T will always be
`KnownSize`, right?

Best regards,
Andreas Hindborg