From 426c92ca1bdd33dcbc01d6d66bb5bb4a356f2c54 Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Mon, 6 Jul 2026 13:44:14 +0100 Subject: rust: io: add dynamically-sized `Region` type Currently many I/O related structs carry a `SIZE` parameter to denote the minimum size of the I/O region, while they also carry a field indicating the actual size. Proliferation of the pattern creates a lot of duplicated code, and makes it hard to create typed views of I/O. Introduce a `Region` type that carries the `SIZE` parameter. It is a wrapper of `[u8]`, which makes it dynamically sized with a metadata of `usize`. This way, pointers to `Region` naturally carry size information. This type is required to be 4-byte aligned. Expose the minimum size information via `MIN_SIZE` constant of the `KnownSize` trait. Similarly, expose the minimum alignment information via `KnownSize::MIN_ALIGN`. With these changes, it is possible to add an associated type to `Io` trait to represent the type of I/O region. For untyped regions, this is the newly added `Region` type. Remove `IoKnownSize` as it is no longer necessary. Use the same mechanism to indicate minimum size of PCI config spaces. Reviewed-by: Alexandre Courbot Signed-off-by: Gary Guo Reviewed-by: Daniel Almeida Link: https://patch.msgid.link/20260706-io_projection-v6-1-72cd5d055d54@garyguo.net [ Add brief explanation on MIN_ALIGN. - Danilo ] Signed-off-by: Danilo Krummrich --- rust/kernel/devres.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'rust/kernel/devres.rs') diff --git a/rust/kernel/devres.rs b/rust/kernel/devres.rs index 11ce500e9b76..ed30ccc6e68e 100644 --- a/rust/kernel/devres.rs +++ b/rust/kernel/devres.rs @@ -68,7 +68,6 @@ struct Inner { /// devres::Devres, /// io::{ /// Io, -/// IoKnownSize, /// Mmio, /// MmioRaw, /// PhysAddr, // @@ -297,10 +296,7 @@ impl Devres { /// use kernel::{ /// device::Core, /// devres::Devres, - /// io::{ - /// Io, - /// IoKnownSize, // - /// }, + /// io::Io, /// pci, // /// }; /// -- cgit v1.2.3 From 9734e905119c5f7d7af9dd3e483f9a0d9ee12187 Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Mon, 6 Jul 2026 13:44:18 +0100 Subject: rust: io: generalize `MmioRaw` to pointer to arbitrary type Conceptually, `MmioRaw` is just `__iomem *`, so it should work for any types. Update the existing use case where it represents a region of compile-time known minimum size and run-time known actual size to use the dynamic-sized type `Region` instead. Rename `maxsize` method to reflect that it is the actual size (not a bound) of the region. Implement `Clone` and `Copy` manually, which cannot be derived due to the generic parameter. The use of raw pointers also cause the `Send` and `Sync` auto trait implementation to be lost, so add them back by manual implementation. Reviewed-by: Alexandre Courbot Signed-off-by: Gary Guo Reviewed-by: Daniel Almeida Suggested-by: Danilo Krummrich Link: https://rust-for-linux.zulipchat.com/#narrow/channel/288089-General/topic/Generic.20I.2FO.20backends/near/571198078 Link: https://patch.msgid.link/20260706-io_projection-v6-5-72cd5d055d54@garyguo.net Signed-off-by: Danilo Krummrich --- rust/kernel/devres.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'rust/kernel/devres.rs') diff --git a/rust/kernel/devres.rs b/rust/kernel/devres.rs index ed30ccc6e68e..d0c677fd7932 100644 --- a/rust/kernel/devres.rs +++ b/rust/kernel/devres.rs @@ -70,14 +70,15 @@ struct Inner { /// Io, /// Mmio, /// MmioRaw, -/// PhysAddr, // +/// PhysAddr, +/// Region, // /// }, /// prelude::*, /// }; /// use core::ops::Deref; /// /// // See also [`pci::Bar`] for a real example. -/// struct IoMem(MmioRaw); +/// struct IoMem(MmioRaw>); /// /// impl IoMem { /// /// # Safety @@ -92,7 +93,7 @@ struct Inner { /// return Err(ENOMEM); /// } /// -/// Ok(IoMem(MmioRaw::new(addr as usize, SIZE)?)) +/// Ok(IoMem(MmioRaw::new_region(addr as usize, SIZE)?)) /// } /// } /// -- cgit v1.2.3 From 691c75967d44bef006e4d4e783baa88470b33ea5 Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Mon, 6 Jul 2026 13:44:19 +0100 Subject: rust: io: rename `Mmio` to `MmioOwned` Most users would more commonly reach out to a view of `Mmio` rather than an owned instance of `Mmio`. Only implementor of `Io` like `Bar` or `IoMem` would need the owned version. Thus, rename `Mmio` to `MmioOwned` so that the name `Mmio` can be used for the view type instead. Reviewed-by: Alexandre Courbot Signed-off-by: Gary Guo Reviewed-by: Daniel Almeida Suggested-by: Danilo Krummrich Link: https://rust-for-linux.zulipchat.com/#narrow/channel/288089-General/topic/Generic.20I.2FO.20backends/near/571198078 Link: https://patch.msgid.link/20260706-io_projection-v6-6-72cd5d055d54@garyguo.net Signed-off-by: Danilo Krummrich --- rust/kernel/devres.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'rust/kernel/devres.rs') diff --git a/rust/kernel/devres.rs b/rust/kernel/devres.rs index d0c677fd7932..aed0c994fd30 100644 --- a/rust/kernel/devres.rs +++ b/rust/kernel/devres.rs @@ -68,7 +68,7 @@ struct Inner { /// devres::Devres, /// io::{ /// Io, -/// Mmio, +/// MmioOwned, /// MmioRaw, /// PhysAddr, /// Region, // @@ -105,11 +105,11 @@ struct Inner { /// } /// /// impl Deref for IoMem { -/// type Target = Mmio; +/// type Target = MmioOwned; /// /// fn deref(&self) -> &Self::Target { /// // SAFETY: The memory range stored in `self` has been properly mapped in `Self::new`. -/// unsafe { Mmio::from_raw(&self.0) } +/// unsafe { MmioOwned::from_raw(&self.0) } /// } /// } /// # fn no_run(dev: &Device) -> Result<(), Error> { -- cgit v1.2.3 From bed01ca9e9cf8f8fea5352c07fa206cc3c106045 Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Mon, 6 Jul 2026 13:44:24 +0100 Subject: rust: io: remove `MmioOwned` `Io` trait is now very easy to implement. Thus, implement it on `Bar` and `IoMem` directly and remove the `MmioOwned` struct. Reviewed-by: Alexandre Courbot Signed-off-by: Gary Guo Reviewed-by: Daniel Almeida Suggested-by: Danilo Krummrich Link: https://rust-for-linux.zulipchat.com/#narrow/channel/288089-General/topic/Generic.20I.2FO.20backends/near/571198078 Link: https://patch.msgid.link/20260706-io_projection-v6-11-72cd5d055d54@garyguo.net Signed-off-by: Danilo Krummrich --- rust/kernel/devres.rs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'rust/kernel/devres.rs') diff --git a/rust/kernel/devres.rs b/rust/kernel/devres.rs index aed0c994fd30..3545ffc5345d 100644 --- a/rust/kernel/devres.rs +++ b/rust/kernel/devres.rs @@ -68,8 +68,9 @@ struct Inner { /// devres::Devres, /// io::{ /// Io, -/// MmioOwned, +/// Mmio, /// MmioRaw, +/// MmioBackend, /// PhysAddr, /// Region, // /// }, @@ -104,12 +105,13 @@ struct Inner { /// } /// } /// -/// impl Deref for IoMem { -/// type Target = MmioOwned; +/// impl<'a, const SIZE: usize> Io<'a> for &'a IoMem { +/// type Backend = MmioBackend; +/// type Target = Region; /// -/// fn deref(&self) -> &Self::Target { +/// fn as_view(self) -> Mmio<'a, Region> { /// // SAFETY: The memory range stored in `self` has been properly mapped in `Self::new`. -/// unsafe { MmioOwned::from_raw(&self.0) } +/// unsafe { Mmio::from_raw(self.0) } /// } /// } /// # fn no_run(dev: &Device) -> Result<(), Error> { -- cgit v1.2.3 From 9b36c13cbd4fb761212b1ea9a2e89f7df2d3c9f8 Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Mon, 6 Jul 2026 13:44:25 +0100 Subject: rust: io: move `Io` methods to extension trait `Io` trait now has a single required method with many more provided methods. Provided methods may want to rely on their implementations to not be arbitrarily overridden by implementers for correctness or soundness. A good example is the `size` method, it may be relied by unsafe code and thus must be consistent with the metadata obtained from `as_ptr`. Thus, create a new trait to host `size` method, extract existing provided methods to the new trait, and provide a blanket implementation. This pattern is used extensively in userspace Rust libraries e.g. `tokio` where `AsyncRead` has minimum methods and `AsyncReadExt` is what users mostly interact with. To avoid changing all user imports, the base trait is renamed to `IoBase` and the newly added trait takes the existing `Io` name. Reviewed-by: Alexandre Courbot Suggested-by: Danilo Krummrich Signed-off-by: Gary Guo Reviewed-by: Daniel Almeida Link: https://patch.msgid.link/20260706-io_projection-v6-12-72cd5d055d54@garyguo.net [ Add comment explaining the purpose of the Io blanket implementation. - Danilo ] Signed-off-by: Danilo Krummrich --- rust/kernel/devres.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'rust/kernel/devres.rs') diff --git a/rust/kernel/devres.rs b/rust/kernel/devres.rs index 3545ffc5345d..6e0b845b229b 100644 --- a/rust/kernel/devres.rs +++ b/rust/kernel/devres.rs @@ -68,6 +68,7 @@ struct Inner { /// devres::Devres, /// io::{ /// Io, +/// IoBase, /// Mmio, /// MmioRaw, /// MmioBackend, @@ -105,7 +106,7 @@ struct Inner { /// } /// } /// -/// impl<'a, const SIZE: usize> Io<'a> for &'a IoMem { +/// impl<'a, const SIZE: usize> IoBase<'a> for &'a IoMem { /// type Backend = MmioBackend; /// type Target = Region; /// -- cgit v1.2.3