> On 6 Jul 2026, at 09:44, Gary Guo <[email protected]> wrote:
> 
> From: Laura Nao <[email protected]>
> 
> Add `SysMem`, an `Io` trait implementation for kernel virtual address
> ranges. It uses volatile accessors to provide safe access to shared
> memory that may be concurrently accessed by external hardware. Implement
> `IoCapable` for `u8`, `u16`, `u32`, and `u64` (for 64-bit system).
> 
> This can be used instead of `Coherent` for cases where a different layer
> takes care of mapping the system memory to the device (e.g. dma-buf or
> GPUVM).
> 
> Signed-off-by: Laura Nao <[email protected]>
> [ Rebased and adapted on top of I/O rework. - Gary ]
> Co-developed-by: Gary Guo <[email protected]>
> Signed-off-by: Gary Guo <[email protected]>
> Reviewed-by: Alexandre Courbot <[email protected]>
> ---
> rust/kernel/io.rs | 122 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 122 insertions(+)
> 
> diff --git a/rust/kernel/io.rs b/rust/kernel/io.rs
> index 62643b23e904..78c6ae2a0db8 100644
> --- a/rust/kernel/io.rs
> +++ b/rust/kernel/io.rs
> @@ -1039,6 +1039,128 @@ pub fn relaxed(self) -> RelaxedMmio<'a, T> {
> #[cfg(CONFIG_64BIT)]
> impl_mmio_io_capable!(RelaxedMmioBackend, u64, readq_relaxed, writeq_relaxed);
> 
> +/// I/O Backend for system memory.
> +pub struct SysMemBackend;
> +
> +impl IoBackend for SysMemBackend {
> +    type View<'a, T: ?Sized + KnownSize> = SysMem<'a, T>;
> +
> +    #[inline]
> +    fn as_ptr<'a, T: ?Sized + KnownSize>(view: Self::View<'a, T>) -> *mut T {
> +        view.ptr
> +    }
> +
> +    #[inline]
> +    unsafe fn project_view<'a, T: ?Sized + KnownSize, U: ?Sized + KnownSize>(
> +        _view: Self::View<'a, T>,
> +        ptr: *mut U,
> +    ) -> Self::View<'a, U> {
> +        // INVARIANT: Per safety requirement, `ptr` is projection from 
> `view`, so it is also a valid
> +        // kernel accessible memory region.
> +        SysMem {
> +            ptr,
> +            phantom: PhantomData,
> +        }
> +    }
> +}
> +
> +/// Implements [`IoCapable`] on `SysMemBackend` for `$ty` using 
> `read_volatile` and
> +/// `write_volatile`.
> +macro_rules! impl_sysmem_io_capable {
> +    ($ty:ty) => {
> +        impl IoCapable<$ty> for SysMemBackend {
> +            #[inline]
> +            fn io_read(view: SysMem<'_, $ty>) -> $ty {
> +                // SAFETY:
> +                // - Per type invariant, `ptr` is valid and aligned.
> +                // - Using read_volatile() here so that race with hardware 
> is well-defined.
> +                // - Using read_volatile() here is not sound if it races 
> with other CPU per Rust
> +                //   rules, but this is allowed per LKMM.
> +                // - The macro is only used on primitives so all bit 
> patterns are valid.
> +                unsafe { view.ptr.read_volatile() }
> +            }
> +
> +            #[inline]
> +            fn io_write(view: SysMem<'_, $ty>, value: $ty) {
> +                // SAFETY:
> +                // - Per type invariant, `ptr` is valid and aligned.
> +                // - Using write_volatile() here so that race with hardware 
> is well-defined.
> +                // - Using write_volatile() here is not sound if it races 
> with other CPU per Rust
> +                //   rules, but this is allowed per LKMM.
> +                unsafe { view.ptr.write_volatile(value) }
> +            }
> +        }
> +    };
> +}
> +
> +impl_sysmem_io_capable!(u8);
> +impl_sysmem_io_capable!(u16);
> +impl_sysmem_io_capable!(u32);
> +#[cfg(CONFIG_64BIT)]
> +impl_sysmem_io_capable!(u64);
> +
> +/// A view of a system memory region.
> +///
> +/// Provides `Io` trait implementation for kernel virtual address ranges,
> +/// using volatile read/write to safely access shared memory that may be
> +/// concurrently accessed by external hardware.
> +///
> +/// # Invariants
> +///
> +/// `self.ptr.addr() .. self.ptr.addr() + KnownSize::size(self.ptr)` is 
> valid and aligned kernel
> +/// accessible memory region for the lifetime `'a`.
> +pub struct SysMem<'a, T: ?Sized> {
> +    ptr: *mut T,
> +    phantom: PhantomData<&'a ()>,
> +}
> +
> +impl<T: ?Sized> Copy for SysMem<'_, T> {}
> +impl<T: ?Sized> Clone for SysMem<'_, T> {
> +    #[inline]
> +    fn clone(&self) -> Self {
> +        *self
> +    }
> +}
> +
> +// SAFETY: `SysMem<'_, T>` is conceptually `&T`.
> +unsafe impl<T: ?Sized + Sync> Send for SysMem<'_, T> {}
> +
> +// SAFETY: `SysMem<'_, T>` is conceptually `&T`.
> +unsafe impl<T: ?Sized + Sync> Sync for SysMem<'_, T> {}
> +
> +impl<'a, T: ?Sized> SysMem<'a, T> {
> +    /// Create a `SysMem` from a raw pointer.
> +    ///
> +    /// # Safety
> +    ///
> +    /// `ptr.addr() .. ptr.addr() + KnownSize::size(ptr)` must be valid and 
> aligned kernel
> +    /// accessible memory region for the lifetime `'a`.
> +    #[inline]
> +    pub unsafe fn new(ptr: *mut T) -> Self {
> +        // INVARIANT: Per safety requirement.
> +        Self {
> +            ptr,
> +            phantom: PhantomData,
> +        }
> +    }
> +
> +    /// Obtain the raw pointer to the memory.
> +    #[inline]
> +    pub fn as_ptr(self) -> *mut T {
> +        self.ptr
> +    }
> +}
> +
> +impl<'a, T: ?Sized + KnownSize> IoBase<'a> for SysMem<'a, T> {
> +    type Backend = SysMemBackend;
> +    type Target = T;
> +
> +    #[inline]
> +    fn as_view(self) -> <Self::Backend as IoBackend>::View<'a, Self::Target> 
> {
> +        self
> +    }
> +}
> +
> // This helper turns associated functions to methods so it can be invoked in 
> macro.
> // Used by `io_project!()` only.
> #[doc(hidden)]
> 
> -- 
> 2.54.0
> 

Reviewed-by: Daniel Almeida <[email protected]>

Reply via email to