lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [day] [month] [year] [list]
Message-ID: <tencent_63DD850B43CC086844717B73C574B8358F05@qq.com>
Date: Wed,  7 Jan 2026 16:14:40 +0800
From: 1064094935@...com
To: Miguel Ojeda <ojeda@...nel.org>
Cc: Boqun Feng <boqun.feng@...il.com>,
	Gary Guo <gary@...yguo.net>,
	Björn Roy Baron <bjorn3_gh@...tonmail.com>,
	Benno Lossin <lossin@...nel.org>,
	Andreas Hindborg <a.hindborg@...nel.org>,
	Alice Ryhl <aliceryhl@...gle.com>,
	Trevor Gross <tmgross@...ch.edu>,
	Danilo Krummrich <dakr@...nel.org>,
	Daniel Almeida <daniel.almeida@...labora.com>,
	FUJITA Tomonori <fujita.tomonori@...il.com>,
	rust-for-linux@...r.kernel.org,
	linux-kernel@...r.kernel.org,
	pengfuyuan <pengfuyuan@...inos.cn>
Subject: [PATCH] rust: io: mem: add ioremap_wc support

From: pengfuyuan <pengfuyuan@...inos.cn>

Add write-combining memory mapping support to the Rust iomem abstraction.
This extends the existing IoMem and IoRequest abstractions to support
write-combining cache policy, which is essential for framebuffer memory
and other memory regions that benefit from write-combining semantics.

The implementation follows the same pattern as the existing ioremap and
ioremap_np support:
- Add rust_helper_ioremap_wc() in rust/helpers/io.c to wrap the C API
- Add IoMem::ioremap_wc() to perform the actual mapping with write-combining
- Add IoMem::new_wc() to create IoMem instances with write-combining policy
- Add IoRequest::iomap_wc_sized() and IoRequest::iomap_wc() methods
  for compile-time and runtime-sized mappings respectively

This enables Rust drivers, such as framebuffer drivers, to properly map
memory regions with write-combining semantics.

The API design is consistent with the existing iomap() methods, providing
both sized and unsized variants to match the pattern established by the
generic iomem abstraction.

Signed-off-by: pengfuyuan <pengfuyuan@...inos.cn>
---
 rust/helpers/io.c     |  5 +++
 rust/kernel/io/mem.rs | 71 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 76 insertions(+)

diff --git a/rust/helpers/io.c b/rust/helpers/io.c
index c475913c69e6..6c9edf7f2233 100644
--- a/rust/helpers/io.c
+++ b/rust/helpers/io.c
@@ -13,6 +13,11 @@ void __iomem *rust_helper_ioremap_np(phys_addr_t offset, size_t size)
 	return ioremap_np(offset, size);
 }
 
+void __iomem *rust_helper_ioremap_wc(phys_addr_t offset, size_t size)
+{
+	return ioremap_wc(offset, size);
+}
+
 void rust_helper_iounmap(void __iomem *addr)
 {
 	iounmap(addr);
diff --git a/rust/kernel/io/mem.rs b/rust/kernel/io/mem.rs
index b03b82cd531b..94403d899bbd 100644
--- a/rust/kernel/io/mem.rs
+++ b/rust/kernel/io/mem.rs
@@ -149,6 +149,41 @@ pub fn iomap(self) -> impl PinInit<Devres<IoMem<0>>, Error> + 'a {
     pub fn iomap_exclusive(self) -> impl PinInit<Devres<ExclusiveIoMem<0>>, Error> + 'a {
         Self::iomap_exclusive_sized::<0>(self)
     }
+
+    /// Maps an [`IoRequest`] with write-combining cache policy where the size
+    /// is known at compile time.
+    ///
+    /// This uses the [`ioremap_wc()`] C API, which provides write-combining
+    /// semantics. This is useful for framebuffer memory and other memory
+    /// regions that benefit from write-combining, where multiple writes can
+    /// be combined and reordered for better performance.
+    ///
+    /// Unlike [`Self::iomap`], this method explicitly uses write-combining
+    /// mapping, which is typically needed for video framebuffers.
+    ///
+    /// [`ioremap_wc()`]: https://docs.kernel.org/driver-api/device-io.html#getting-access-to-the-device
+    pub fn iomap_wc_sized<const SIZE: usize>(
+        self,
+    ) -> impl PinInit<Devres<IoMem<SIZE>>, Error> + 'a {
+        IoMem::new_wc(self)
+    }
+
+    /// Maps an [`IoRequest`] with write-combining cache policy where the size
+    /// is not known at compile time.
+    ///
+    /// This uses the [`ioremap_wc()`] C API, which provides write-combining
+    /// semantics. This is useful for framebuffer memory and other memory
+    /// regions that benefit from write-combining.
+    ///
+    /// Unlike [`Self::iomap_wc_sized`], here the size of the memory region
+    /// is not known at compile time, so only the `try_read*` and `try_write*`
+    /// family of functions should be used, leading to runtime checks on every
+    /// access.
+    ///
+    /// [`ioremap_wc()`]: https://docs.kernel.org/driver-api/device-io.html#getting-access-to-the-device
+    pub fn iomap_wc(self) -> impl PinInit<Devres<IoMem<0>>, Error> + 'a {
+        Self::iomap_wc_sized::<0>(self)
+    }
 }
 
 /// An exclusive memory-mapped IO region.
@@ -261,6 +296,33 @@ fn ioremap(resource: &Resource) -> Result<Self> {
         Ok(io)
     }
 
+    fn ioremap_wc(resource: &Resource) -> Result<Self> {
+        // Note: Some ioremap() implementations use types that depend on the CPU
+        // word width rather than the bus address width.
+        //
+        // TODO: Properly address this in the C code to avoid this `try_into`.
+        let size = resource.size().try_into()?;
+        if size == 0 {
+            return Err(EINVAL);
+        }
+
+        let res_start = resource.start();
+
+        // SAFETY:
+        // - `res_start` and `size` are read from a presumably valid `struct resource`.
+        // - `size` is known not to be zero at this point.
+        let addr = unsafe { bindings::ioremap_wc(res_start, size) };
+
+        if addr.is_null() {
+            return Err(ENOMEM);
+        }
+
+        let io = IoRaw::new(addr as usize, size)?;
+        let io = IoMem { io };
+
+        Ok(io)
+    }
+
     /// Creates a new `IoMem` instance from a previously acquired [`IoRequest`].
     pub fn new<'a>(io_request: IoRequest<'a>) -> impl PinInit<Devres<Self>, Error> + 'a {
         let dev = io_request.device;
@@ -268,6 +330,15 @@ pub fn new<'a>(io_request: IoRequest<'a>) -> impl PinInit<Devres<Self>, Error> +
 
         Devres::new(dev, Self::ioremap(res))
     }
+
+    /// Creates a new `IoMem` instance with write-combining cache policy from
+    /// a previously acquired [`IoRequest`].
+    pub fn new_wc<'a>(io_request: IoRequest<'a>) -> impl PinInit<Devres<Self>, Error> + 'a {
+        let dev = io_request.device;
+        let res = io_request.resource;
+
+        Devres::new(dev, Self::ioremap_wc(res))
+    }
 }
 
 impl<const SIZE: usize> Drop for IoMem<SIZE> {
-- 
2.25.1


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ