Rust for Linux List
 help / color / mirror / Atom feed
From: "Gary Guo" <gary@garyguo.net>
To: "Link Mauve" <linkmauve@linkmauve.fr>, <rust-for-linux@vger.kernel.org>
Cc: "Ethan Plant" <plant.ethan@gmail.com>,
	"Michael Garofalo" <officialTechflashYT@gmail.com>,
	"Ash Logan" <ash@heyquark.com>,
	"Jonathan Neuschäfer" <j.neuschaefer@gmx.net>,
	"Sasha Finkelstein" <k@chaosmail.tech>,
	"Miguel Ojeda" <ojeda@kernel.org>,
	"Boqun Feng" <boqun@kernel.org>, "Gary Guo" <gary@garyguo.net>,
	"Björn Roy Baron" <bjorn3_gh@protonmail.com>,
	"Benno Lossin" <lossin@kernel.org>,
	"Andreas Hindborg" <a.hindborg@kernel.org>,
	"Alice Ryhl" <aliceryhl@google.com>,
	"Trevor Gross" <tmgross@umich.edu>,
	"Danilo Krummrich" <dakr@kernel.org>,
	"Daniel Almeida" <daniel.almeida@collabora.com>,
	"Tamir Duberstein" <tamird@kernel.org>,
	"Alexandre Courbot" <acourbot@nvidia.com>,
	"Onur Özkan" <work@onurozkan.dev>,
	linux-kernel@vger.kernel.org, driver-core@lists.linux.dev
Subject: Re: [PATCH v2] rust: io: Add a BigEndianMmio wrapper
Date: Thu, 06 Aug 2026 12:44:31 +0100	[thread overview]
Message-ID: <DKHU2JQ95D67.33B9B0U3539IA@garyguo.net> (raw)
In-Reply-To: <20260806062207.3024012-1-linkmauve@linkmauve.fr>

On Thu Aug 6, 2026 at 7:22 AM BST, Link Mauve wrote:
> This allows the user to read from and write to big-endian MMIO devices,
> such as those found on PowerPC systems.
>
> The implementation is pretty much a copy-paste of the RelaxedMmio type,
> with the business logic changed.
>
> This has been tested with various WIP drivers on the Nintendo Wii, and I
> thought it would be nicer to upstream it before those are completely
> ready, to get some review.

An alternative approach would be to have a generic wrapper `BigEndian<IO>` where
it performs byte-swapping in its `IoCapable` implementation. This is more
composable as it works for all I/O.

Of course, this means that it won't be using the specialized BE I/O impl, but
then the only architectures that have specialized ioread16be are PPC32 and
SPARC, so maybe it's a reasonable trade-off to make?

Best,
Gary

>
> Signed-off-by: Link Mauve <linkmauve@linkmauve.fr>
> ---
>  rust/helpers/io.c | 34 ++++++++++++++++++
>  rust/kernel/io.rs | 88 +++++++++++++++++++++++++++++++++++++++++++++--
>  2 files changed, 120 insertions(+), 2 deletions(-)
>
> Changes since v1:
> - Link to v1:
>   https://lore.kernel.org/rust-for-linux/178598049138.1212746.2443151507074972963.b4-review@b4/T/
> - Fix copy/paste mistake in backend docstring (thank you Ethan Plant!)
> - Fix safety comment in macro documentation.
>
> diff --git a/rust/helpers/io.c b/rust/helpers/io.c
> index 7ed9a4f77f1b..3bbb86a00d67 100644
> --- a/rust/helpers/io.c
> +++ b/rust/helpers/io.c
> @@ -120,6 +120,40 @@ __rust_helper void rust_helper_writeq_relaxed(u64 value, void __iomem *addr)
>  }
>  #endif
>  
> +__rust_helper u16 rust_helper_ioread16be(const void __iomem *addr)
> +{
> +	return ioread16be(addr);
> +}
> +
> +__rust_helper u32 rust_helper_ioread32be(const void __iomem *addr)
> +{
> +	return ioread32be(addr);
> +}
> +
> +#ifdef CONFIG_64BIT
> +__rust_helper u64 rust_helper_ioread64be(const void __iomem *addr)
> +{
> +	return ioread64be(addr);
> +}
> +#endif
> +
> +__rust_helper void rust_helper_iowrite16be(u16 value, void __iomem *addr)
> +{
> +	iowrite16be(value, addr);
> +}
> +
> +__rust_helper void rust_helper_iowrite32be(u32 value, void __iomem *addr)
> +{
> +	iowrite32be(value, addr);
> +}
> +
> +#ifdef CONFIG_64BIT
> +__rust_helper void rust_helper_iowrite64be(u64 value, void __iomem *addr)
> +{
> +	iowrite64be(value, addr);
> +}
> +#endif
> +
>  __rust_helper resource_size_t rust_helper_resource_size(struct resource *res)
>  {
>  	return resource_size(res);
> diff --git a/rust/kernel/io.rs b/rust/kernel/io.rs
> index a38c20ba3d23..ab8b7864298a 100644
> --- a/rust/kernel/io.rs
> +++ b/rust/kernel/io.rs
> @@ -1194,14 +1194,14 @@ impl IoCapable<$ty> for $backend {
>              #[inline]
>              fn io_read(view: <$backend as IoBackend>::View<'_, $ty>) -> $ty {
>                  // SAFETY: `$backend::as_ptr(view)` is a valid pointer for MMIO operations for both
> -                // `MmioBackend` and `RelaxedMmioBackend`.
> +                // `MmioBackend`, `RelaxedMmioBackend` and `BigEndianMmioBackend`.
>                  unsafe { bindings::$read_fn($backend::as_ptr(view).cast_const().cast()) }
>              }
>  
>              #[inline]
>              fn io_write(view: <$backend as IoBackend>::View<'_, $ty>, value: $ty) {
>                  // SAFETY: `$backend::as_ptr(view)` is a valid pointer for MMIO operations for both
> -                // `MmioBackend` and `RelaxedMmioBackend`.
> +                // `MmioBackend`, `RelaxedMmioBackend` and `BigEndianMmioBackend`.
>                  unsafe { bindings::$write_fn(value, $backend::as_ptr(view).cast()) }
>              }
>          }
> @@ -1751,3 +1751,87 @@ macro_rules! io_write {
>  }
>  #[doc(inline)]
>  pub use crate::io_write;
> +
> +/// [`Mmio`] wrapper using big-endian accessors.
> +///
> +/// This type provides an implementation of [`Io`] that uses big-endian I/O MMIO operands instead of
> +/// the regular little-endian ones.
> +///
> +/// See [`Mmio::big_endian`] for a usage example.
> +#[repr(transparent)]
> +pub struct BigEndianMmio<'a, T: ?Sized>(Mmio<'a, T>);
> +
> +impl<T: ?Sized> Copy for BigEndianMmio<'_, T> {}
> +impl<T: ?Sized> Clone for BigEndianMmio<'_, T> {
> +    #[inline]
> +    fn clone(&self) -> Self {
> +        *self
> +    }
> +}
> +
> +/// I/O Backend for memory-mapped I/O using big-endian accessors.
> +pub struct BigEndianMmioBackend;
> +
> +impl IoBackend for BigEndianMmioBackend {
> +    type View<'a, T: ?Sized + KnownSize> = BigEndianMmio<'a, T>;
> +
> +    #[inline]
> +    fn as_ptr<'a, T: ?Sized + KnownSize>(view: Self::View<'a, T>) -> *mut T {
> +        MmioBackend::as_ptr(view.0)
> +    }
> +
> +    #[inline]
> +    unsafe fn project_view<'a, T: ?Sized + KnownSize, U: ?Sized + KnownSize>(
> +        view: Self::View<'a, T>,
> +        ptr: *mut U,
> +    ) -> Self::View<'a, U> {
> +        // SAFETY: Per safety requirement.
> +        BigEndianMmio(unsafe { MmioBackend::project_view(view.0, ptr) })
> +    }
> +}
> +
> +impl<'a, T: ?Sized + KnownSize> IoBase<'a> for BigEndianMmio<'a, T> {
> +    type Backend = BigEndianMmioBackend;
> +    type Target = T;
> +
> +    #[inline]
> +    fn as_view(self) -> BigEndianMmio<'a, T> {
> +        self
> +    }
> +}
> +
> +impl<'a, T: ?Sized> Mmio<'a, T> {
> +    /// Returns a [`BigEndianMmio`] reference that performs big-endian I/O operations.
> +    ///
> +    /// Big-endian makes no change to 8-bit accesses, but will invert the bytes of 16-, 32- and
> +    /// 64-bit accesses, to ensure numbers will be read in their correct order.
> +    ///
> +    /// # Examples
> +    ///
> +    /// ```no_run
> +    /// use kernel::io::{
> +    ///     Io,
> +    ///     Mmio,
> +    ///     Region,
> +    ///     BigEndianMmio,
> +    /// };
> +    ///
> +    /// fn do_io(io: Mmio<'_, Region<0x100>>) {
> +    ///     // The access is performed using `ioread32be` instead of `readl`.
> +    ///     let v = io.big_endian().read32(0x10);
> +    /// }
> +    ///
> +    /// ```
> +    #[inline]
> +    pub fn big_endian(self) -> BigEndianMmio<'a, T> {
> +        BigEndianMmio(self)
> +    }
> +}
> +
> +// MMIO regions support 8, 16, and 32-bit accesses.
> +impl_mmio_io_capable!(BigEndianMmioBackend, u8, readb, writeb);
> +impl_mmio_io_capable!(BigEndianMmioBackend, u16, ioread16be, iowrite16be);
> +impl_mmio_io_capable!(BigEndianMmioBackend, u32, ioread32be, iowrite32be);
> +// MMIO regions on 64-bit systems also support 64-bit accesses.
> +#[cfg(CONFIG_64BIT)]
> +impl_mmio_io_capable!(BigEndianMmioBackend, u64, ioread64be, iowrite64be);
>
> base-commit: 1701fda2f58e345c050f4309971bdc07cd6146ba



  reply	other threads:[~2026-08-06 11:44 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-06  6:22 [PATCH v2] rust: io: Add a BigEndianMmio wrapper Link Mauve
2026-08-06 11:44 ` Gary Guo [this message]
2026-08-06 12:13   ` Link Mauve

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=DKHU2JQ95D67.33B9B0U3539IA@garyguo.net \
    --to=gary@garyguo.net \
    --cc=a.hindborg@kernel.org \
    --cc=acourbot@nvidia.com \
    --cc=aliceryhl@google.com \
    --cc=ash@heyquark.com \
    --cc=bjorn3_gh@protonmail.com \
    --cc=boqun@kernel.org \
    --cc=dakr@kernel.org \
    --cc=daniel.almeida@collabora.com \
    --cc=driver-core@lists.linux.dev \
    --cc=j.neuschaefer@gmx.net \
    --cc=k@chaosmail.tech \
    --cc=linkmauve@linkmauve.fr \
    --cc=linux-kernel@vger.kernel.org \
    --cc=lossin@kernel.org \
    --cc=officialTechflashYT@gmail.com \
    --cc=ojeda@kernel.org \
    --cc=plant.ethan@gmail.com \
    --cc=rust-for-linux@vger.kernel.org \
    --cc=tamird@kernel.org \
    --cc=tmgross@umich.edu \
    --cc=work@onurozkan.dev \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox