[PATCH 07/10] rust: io: add subregion method with compile-time check

Gary Guo <[email protected]> Tue, 21 Jul 2026 17:54:31 +0100
Newsgroups dev.linux.lists.nova-gpu,dev.linux.lists.driver-core,org.freedesktop.lists.dri-devel,org.kernel.vger.linux-kernel,org.kernel.vger.linux-pci,org.kernel.vger.rust-for-linux
Message-ID <[email protected]>
Add a helper function that allows obtaining a subregion from region with
compile-time check. This can be used by drivers to obtaining a subregion
for relative register access.

Signed-off-by: Gary Guo <[email protected]>
---
 rust/kernel/io.rs | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/rust/kernel/io.rs b/rust/kernel/io.rs
index 0f8b166a6d3b..f31d37c8a3d5 100644
--- a/rust/kernel/io.rs
+++ b/rust/kernel/io.rs
@@ -80,6 +80,30 @@ pub fn ptr_try_from_raw_parts_mut(base: *mut u8, size: usize) -> Result<*mut Sel
 
         Ok(Self::ptr_from_raw_parts_mut(base, size))
     }
+
+    /// Create a subregion with provided offset and size.
+    #[inline]
+    pub fn subregion<'a, const OFFSET: usize, const NEW_SIZE: usize, IO>(
+        io: IO,
+    ) -> <IO::Backend as IoBackend>::View<'a, Region<NEW_SIZE>>
+    where
+        IO: IoBase<'a, Target = Self>,
+    {
+        const_assert!(
+            OFFSET + NEW_SIZE <= SIZE && OFFSET.is_multiple_of(4) && NEW_SIZE.is_multiple_of(4)
+        );
+
+        let view = io.as_view();
+        let ptr = IO::Backend::as_ptr(view) as *mut [u8];
+        let new_ptr = Region::ptr_from_raw_parts_mut(
+            ptr.cast::<u8>().wrapping_add(OFFSET),
+            ptr.len() - OFFSET,
+        );
+
+        // SAFETY: We have checked that the new region is a subregion and it is aligned, hence it is
+        // a valid projection.
+        unsafe { IO::Backend::project_view(view, new_ptr) }
+    }
 }
 
 impl<const SIZE: usize> KnownSize for Region<SIZE> {

-- 
2.54.0