Re: [PATCH v5 00/20] rust: I/O type generalization and projection

"Danilo Krummrich" <[email protected]>
Newsgroups org.kernel.vger.linux-pwm,dev.linux.lists.driver-core,dev.linux.lists.nova-gpu,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]>
On Fri Jun 26, 2026 at 4:45 PM CEST, Gary Guo wrote:
> This series presents a major rework of I/O types, as a summary:

There are two minor rustdoc warnings:

	warning: unresolved link to `include/linux/iosys-map.h`
	    --> rust/kernel/io.rs:1456:7
	     |
	1456 | /// [`include/linux/iosys-map.h`] in C.
	     |       ^^^^^^^^^^^^^^^^^^^^^^^^^ no item named `include/linux/iosys-map.h` in scope
	     |
	     = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
	     = note: `#[warn(rustdoc::broken_intra_doc_links)]` on by default
	
	warning: unresolved link to `View`
	    --> rust/kernel/io.rs:1620:74
	     |
	1620 | /// In addition to projecting from [`Io`], you may also project from a [`View`] of an [`Io`].
	     |                                                                          ^^^^ no item named `View` in scope
	     |
	     = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
	
	warning: 2 warnings emitted

> Gary Guo (19):
>       rust: io: add dynamically-sized `Region` type
>       rust: io: add missing safety requirement in `IoCapable` methods
>       rust: io: restrict untyped IO access and `register!` to `Region`
>       rust: io: implement `Io` on reference types instead
>       rust: io: generalize `MmioRaw` to pointer to arbitrary type
>       rust: io: rename `Mmio` to `MmioOwned`
>       rust: io: implement `Mmio` as view type
>       rust: pci: io: make `ConfigSpace` a view
>       rust: io: use view types instead of addresses for `Io`
>       pwm: th1520: remove unnecessary `deref`
>       rust: io: remove `MmioOwned`
>       rust: io: move `Io` methods to extension trait
>       rust: io: add projection macro and methods
>       rust: io: implement a view type for `Coherent`
>       rust: io: add `read_val` and `write_val` functions on `Io`
>       gpu: nova-core: use I/O projection for cleaner encapsulation
>       rust: dma: drop `dma_read!` and `dma_write!` API
>       rust: io: add copying methods
>       rust: io: implement `IoSysMap`
>
> Laura Nao (1):
>       rust: io: add I/O backend for system memory with volatile access

For sharing with the drm-rust tree:

diff --git a/rust/kernel/drm/gem/shmem.rs b/rust/kernel/drm/gem/shmem.rs
index 3ee19ef6264e..6868b5d80ab7 100644
--- a/rust/kernel/drm/gem/shmem.rs
+++ b/rust/kernel/drm/gem/shmem.rs
@@ -29,9 +29,10 @@
         to_result, //
     },
     io::{
-        Io,
-        IoCapable,
-        IoKnownSize, //
+        IoBase,
+        Region,
+        SysMem,
+        SysMemBackend, //
     },
     prelude::*,
     scatterlist,
@@ -467,6 +468,28 @@ pub fn owner(&self) -> &Object<D, C> {
     }
 }

+impl<'a, D, R, C, const SIZE: usize> IoBase<'a> for &'a VMap<D, R, C, SIZE>
+where
+    D: DriverObject,
+    C: DeviceContext,
+    R: Deref<Target = Object<D, C>>,
+{
+    type Backend = SysMemBackend;
+    type Target = Region<SIZE>;
+
+    #[inline]
+    fn as_view(self) -> SysMem<'a, Region<SIZE>> {
+        let ptr = Region::ptr_from_raw_parts_mut(self.addr.cast(), self.owner.size());
+
+        // SAFETY: Per type invariants of `VMap`:
+        // - `addr .. addr + owner.size()` is a valid kernel accessible memory region.
+        // - `addr` is page-aligned, which satisfies `Region`'s 4-byte alignment requirement.
+        // - The memory remains valid until this `VMap` is dropped; since `self` is `&'a VMap`,
+        //   the borrow prevents the `VMap` from being dropped for the lifetime `'a`.
+        unsafe { SysMem::new(ptr) }
+    }
+}
+
 impl<D, R, C, const SIZE: usize> Drop for VMap<D, R, C, SIZE>
 where
     D: DriverObject,
@@ -508,69 +531,6 @@ unsafe impl<D, R, C, const SIZE: usize> Sync for VMap<D, R, C, SIZE>
 {
 }

-impl<D, R, C, const SIZE: usize> Io for VMap<D, R, C, SIZE>
-where
-    D: DriverObject,
-    C: DeviceContext,
-    R: Deref<Target = Object<D, C>>,
-{
-    #[inline]
-    fn addr(&self) -> usize {
-        self.addr as usize
-    }
-
-    #[inline]
-    fn maxsize(&self) -> usize {
-        self.owner.size()
-    }
-}
-
-impl<D, R, C, const SIZE: usize> IoKnownSize for VMap<D, R, C, SIZE>
-where
-    D: DriverObject,
-    C: DeviceContext,
-    R: Deref<Target = Object<D, C>>,
-{
-    const MIN_SIZE: usize = SIZE;
-}
-
-macro_rules! impl_vmap_io_capable {
-    ($ty:ty) => {
-        impl<D, R, C, const SIZE: usize> IoCapable<$ty> for VMap<D, R, C, SIZE>
-        where
-            D: DriverObject,
-            C: DeviceContext,
-            R: Deref<Target = Object<D, C>>,
-        {
-            #[inline]
-            unsafe fn io_read(&self, address: usize) -> $ty {
-                let ptr = address as *mut $ty;
-
-                // SAFETY: The safety contract of `io_read` guarantees that address is a valid
-                // address within the bounds of `Self` of at least the size of $ty, and is properly
-                // aligned.
-                unsafe { ptr::read_volatile(ptr) }
-            }
-
-            #[inline]
-            unsafe fn io_write(&self, value: $ty, address: usize) {
-                let ptr = address as *mut $ty;
-
-                // SAFETY: The safety contract of `io_write` guarantees that address is a valid
-                // address within the bounds of `Self` of at least the size of $ty, and is properly
-                // aligned.
-                unsafe { ptr::write_volatile(ptr, value) }
-            }
-        }
-    };
-}
-
-impl_vmap_io_capable!(u8);
-impl_vmap_io_capable!(u16);
-impl_vmap_io_capable!(u32);
-#[cfg(CONFIG_64BIT)]
-impl_vmap_io_capable!(u64);
-
 /// A reference to a GEM object that is known to have a mapped [`SGTable`].
 ///
 /// This is used by the Rust bindings with [`Devres`] in order to ensure that mappings for SGTables
@@ -638,6 +598,7 @@ mod tests {
             UnregisteredDevice, //
         },
         faux,
+        io::Io,
         page::PAGE_SIZE, //
     };

@@ -714,7 +675,7 @@ fn compile_time_vmap_sizes() -> Result {
         assert!(ptr::eq(vmap.owner(), obj.deref()));

         // Verify the max size matches the actual object size
-        assert_eq!(vmap.maxsize(), PAGE_SIZE);
+        assert_eq!(vmap.size(), PAGE_SIZE);

         // Make sure creating a vmap that's too large fails
         assert!(obj.vmap::<{ PAGE_SIZE + 200 }>().is_err());
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.