From: Charalampos Mitrodimas <charmitro@posteo.net>
To: Daniel Almeida <daniel.almeida@collabora.com>
Cc: alex.gaynor@gmail.com, boqun.feng@gmail.com, gary@garyguo.net,
bjorn3_gh@protonmail.com, benno.lossin@proton.me,
a.hindborg@kernel.org, aliceryhl@google.com, tmgross@umich.edu,
gregkh@linuxfoundation.org, rafael@kernel.org, dakr@kernel.org,
boris.brezillon@collabora.com, rust-for-linux@vger.kernel.org,
linux-kernel@vger.kernel.org
Subject: Re: [PATCH v4 2/3] rust: io: mem: add a generic iomem abstraction
Date: Thu, 09 Jan 2025 13:46:57 +0000 [thread overview]
Message-ID: <m2h668t7zi.fsf@posteo.net> (raw)
In-Reply-To: <20250109133057.243751-3-daniel.almeida@collabora.com> (Daniel Almeida's message of "Thu, 9 Jan 2025 10:30:54 -0300")
Daniel Almeida <daniel.almeida@collabora.com> writes:
> Add a generic iomem abstraction to safely read and write ioremapped
> regions.
>
> The reads and writes are done through IoRaw, and are thus checked either
> at compile-time, if the size of the region is known at that point, or at
> runtime otherwise.
>
> Non-exclusive access to the underlying memory region is made possible to
> cater to cases where overlapped regions are unavoidable.
>
> Signed-off-by: Daniel Almeida <daniel.almeida@collabora.com>
> ---
> rust/helpers/io.c | 10 ++++
> rust/kernel/io.rs | 1 +
> rust/kernel/io/mem.rs | 108 ++++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 119 insertions(+)
> create mode 100644 rust/kernel/io/mem.rs
>
> diff --git a/rust/helpers/io.c b/rust/helpers/io.c
> index 3cb47bd01942..cb10060c08ae 100644
> --- a/rust/helpers/io.c
> +++ b/rust/helpers/io.c
> @@ -106,3 +106,13 @@ resource_size_t rust_helper_resource_size(struct resource *res)
> return resource_size(res);
> }
>
> +struct resource *rust_helper_request_mem_region(resource_size_t start, resource_size_t n,
> + const char *name)
> +{
> + return request_mem_region(start, n, name);
> +}
> +
> +void rust_helper_release_mem_region(resource_size_t start, resource_size_t n)
> +{
> + release_mem_region(start, n);
> +}
> diff --git a/rust/kernel/io.rs b/rust/kernel/io.rs
> index 566d8b177e01..9ce3482b5ecd 100644
> --- a/rust/kernel/io.rs
> +++ b/rust/kernel/io.rs
> @@ -7,6 +7,7 @@
> use crate::error::{code::EINVAL, Result};
> use crate::{bindings, build_assert};
>
> +pub mod mem;
> pub mod resource;
>
> /// Raw representation of an MMIO region.
> diff --git a/rust/kernel/io/mem.rs b/rust/kernel/io/mem.rs
> new file mode 100644
> index 000000000000..f2147db715bf
> --- /dev/null
> +++ b/rust/kernel/io/mem.rs
> @@ -0,0 +1,108 @@
> +// SPDX-License-Identifier: GPL-2.0
> +
> +//! Generic memory-mapped IO.
> +
> +use core::ops::Deref;
> +
> +use crate::io::resource::Resource;
> +use crate::io::Io;
> +use crate::io::IoRaw;
> +use crate::prelude::*;
> +
> +/// A generic memory-mapped IO region.
> +///
> +/// Accesses to the underlying region is checked either at compile time, if the
> +/// region's size is known at that point, or at runtime otherwise.
> +///
> +/// Whether `IoMem` represents an exclusive access to the underlying memory
> +/// region is determined by the caller at creation time, as overlapping access
> +/// may be needed in some cases.
> +///
> +/// # Invariants
> +///
> +/// `IoMem` always holds an `IoRaw` inststance that holds a valid pointer to the
> +/// start of the I/O memory mapped region and its size.
> +pub struct IoMem<const SIZE: usize = 0> {
> + io: IoRaw<SIZE>,
> + res_start: u64,
> + exclusive: bool,
> +}
> +
> +impl<const SIZE: usize> IoMem<SIZE> {
> + /// Creates a new `IoMem` instance.
> + ///
> + /// `exclusive` determines whether the memory region should be exclusively
> + ///
> + /// # Safety
> + ///
> + /// The caller must ensure that the underlying resource remains valid
> + /// throughout the `IoMem`'s lifetime. This is usually done by wrapping the
> + /// `IoMem` in a `Devres` instance, which will properly revoke the access
> + /// when the device is unbound from the matched driver.
> + pub(crate) unsafe fn new(resource: &Resource, exclusive: bool) -> Result<Self> {
> + let size = resource.size();
> + if size == 0 {
> + return Err(ENOMEM);
> + }
Shouldn't this be EINVAL instead? AFAIR, ENOMEM is typically used for
memory allocation failures or resource exhaustion, whereas EINVAL seems
more appropriate for signaling invalid resource configurations
> +
> + let res_start = resource.start();
> +
> + if exclusive {
> + // SAFETY:
> + // - `res_start` and `size` are read from a presumably valid `struct resource`.
> + // - `size` is known not to be zero at this point.
> + // - `resource.name()` returns a valid C string.
> + let mem_region = unsafe {
> + bindings::request_mem_region(res_start, size, resource.name().as_char_ptr())
> + };
> +
> + if mem_region.is_null() {
> + return Err(EBUSY);
> + }
> + }
> +
> + // 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(res_start, size as usize) };
> + if addr.is_null() {
> + if exclusive {
> + // SAFETY:
> + // - `res_start` and `size` are read from a presumably valid `struct resource`.
> + // - `size` is the same as the one passed to `request_mem_region`.
> + unsafe { bindings::release_mem_region(res_start, size) };
> + }
> + return Err(ENOMEM);
> + }
> +
> + let io = IoRaw::new(addr as usize, size as usize)?;
> +
> + Ok(IoMem {
> + io,
> + res_start,
> + exclusive,
> + })
> + }
> +}
> +
> +impl<const SIZE: usize> Drop for IoMem<SIZE> {
> + fn drop(&mut self) {
> + if self.exclusive {
> + // SAFETY: `res_start` and `io.maxsize()` were the values passed to
> + // `request_mem_region`.
> + unsafe { bindings::release_mem_region(self.res_start, self.io.maxsize() as u64) }
> + }
> +
> + // SAFETY: Safe as by the invariant of `Io`.
> + unsafe { bindings::iounmap(self.io.addr() as *mut core::ffi::c_void) }
> + }
> +}
> +
> +impl<const SIZE: usize> Deref for IoMem<SIZE> {
> + type Target = Io<SIZE>;
> +
> + fn deref(&self) -> &Self::Target {
> + // SAFETY: Safe as by the invariant of `IoMem`.
> + unsafe { Io::from_raw(&self.io) }
> + }
> +}
next prev parent reply other threads:[~2025-01-09 13:47 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-12-11 17:51 [PATCH v3] rust: platform: add Io support Daniel Almeida
2024-12-11 18:36 ` Danilo Krummrich
2024-12-11 21:00 ` Daniel Almeida
2024-12-11 21:49 ` Danilo Krummrich
2024-12-12 16:51 ` Rob Herring
2024-12-11 18:41 ` Boqun Feng
2025-01-09 13:30 ` [PATCH v4 0/3] " Daniel Almeida
2025-01-09 13:30 ` [PATCH v4 1/3] rust: io: add resource abstraction Daniel Almeida
2025-01-09 13:46 ` Alice Ryhl
2025-01-16 11:26 ` Fiona Behrens
2025-01-09 13:30 ` [PATCH v4 2/3] rust: io: mem: add a generic iomem abstraction Daniel Almeida
2025-01-09 13:46 ` Charalampos Mitrodimas [this message]
2025-01-09 13:53 ` Alice Ryhl
2025-01-09 15:33 ` Daniel Almeida
2025-01-09 15:40 ` Alice Ryhl
2025-01-09 15:43 ` Daniel Almeida
2025-01-09 13:30 ` [PATCH v4 3/3] rust: platform: allow ioremap of platform resources Daniel Almeida
2025-01-09 14:00 ` Alice Ryhl
2025-01-09 16:04 ` Danilo Krummrich
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=m2h668t7zi.fsf@posteo.net \
--to=charmitro@posteo.net \
--cc=a.hindborg@kernel.org \
--cc=alex.gaynor@gmail.com \
--cc=aliceryhl@google.com \
--cc=benno.lossin@proton.me \
--cc=bjorn3_gh@protonmail.com \
--cc=boqun.feng@gmail.com \
--cc=boris.brezillon@collabora.com \
--cc=dakr@kernel.org \
--cc=daniel.almeida@collabora.com \
--cc=gary@garyguo.net \
--cc=gregkh@linuxfoundation.org \
--cc=linux-kernel@vger.kernel.org \
--cc=rafael@kernel.org \
--cc=rust-for-linux@vger.kernel.org \
--cc=tmgross@umich.edu \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.