Re: [PATCH v4 03/20] rust: io: restrict untyped IO access and `register!` to `Region`

From: Alexandre Courbot

Date: Mon Jun 15 2026 - 01:18:38 EST


On Fri Jun 12, 2026 at 1:28 AM JST, Gary Guo wrote:
> Currently the `Io` trait exposes a bunch of untyped IO accesses, but if the
> `Io` region itself is typed, then it might be weird to have
>
> let io: Mmio<u32> = /* ... */;
> io.read8(1);
>
> while not unsound, it is surely strange. Thus, restrict the untyped methods
> and also the register macro to `Region` type only.
>
> Implement it by adding a generic type to `IoLoc` indicating allowed base
> types. This also paves the way to add typed register blocks in the future;
> for example, we could use this mechanism to block driver A's `register!()`
> generated macro from being used on driver B's MMIO. The same mechanism
> could be used for relative IO registers. These are future opportunities,
> and for now restrict everything to require `IoLoc<Region<SIZE>, _>`.
>
> Suggested-by: Alexandre Courbot <acourbot@xxxxxxxxxx>
> Link: https://lore.kernel.org/rust-for-linux/DHLB3RO3OSF5.2R7F27U99BKLN@xxxxxxxxxx/
> Signed-off-by: Gary Guo <gary@xxxxxxxxxxx>

Reviewed-by: Alexandre Courbot <acourbot@xxxxxxxxxx>

<...>
> --- a/rust/kernel/io/register.rs
> +++ b/rust/kernel/io/register.rs
> @@ -113,6 +113,8 @@
> io::IoLoc, //
> };
>
> +use super::Region;
> +
> /// Trait implemented by all registers.
> pub trait Register: Sized {
> /// Backing primitive type of the register.
> @@ -129,7 +131,7 @@ pub trait FixedRegister: Register {}
>
> /// Allows `()` to be used as the `location` parameter of [`Io::write`](super::Io::write) when
> /// passing a [`FixedRegister`] value.
> -impl<T> IoLoc<T> for ()
> +impl<const SIZE: usize, T> IoLoc<Region<SIZE>, T> for ()
> where
> T: FixedRegister,
> {
> @@ -143,7 +145,7 @@ fn offset(self) -> usize {
>
> /// A [`FixedRegister`] carries its location in its type. Thus `FixedRegister` values can be used
> /// as an [`IoLoc`].
> -impl<T> IoLoc<T> for T
> +impl<const SIZE: usize, T> IoLoc<Region<SIZE>, T> for T
> where
> T: FixedRegister,
> {
> @@ -168,7 +170,7 @@ pub const fn new() -> Self {
> }
> }
>
> -impl<T> IoLoc<T> for FixedRegisterLoc<T>
> +impl<const SIZE: usize, T> IoLoc<Region<SIZE>, T> for FixedRegisterLoc<T>
> where
> T: FixedRegister,
> {
> @@ -239,7 +241,8 @@ const fn offset(self) -> usize {
> }
> }
>
> -impl<T, B> IoLoc<T> for RelativeRegisterLoc<T, B>
> +// FIXME: Make use of `Base` type parameter of `Region` directly.

`Region` does not have any `Base` type parameter, so I am not sure what
this refers to.

Is this to make relative registers tied to a specific register block
type? If so, it would help to expand this FIXME a bit as it might be
difficult to understand without context.