From: Andreas Hindborg <a.hindborg@kernel.org>
To: "Gary Guo" <gary@garyguo.net>
Cc: "Miguel Ojeda" <ojeda@kernel.org>,
"Alex Gaynor" <alex.gaynor@gmail.com>,
"Boqun Feng" <boqun.feng@gmail.com>,
"Björn Roy Baron" <bjorn3_gh@protonmail.com>,
"Benno Lossin" <benno.lossin@proton.me>,
"Alice Ryhl" <aliceryhl@google.com>,
"Trevor Gross" <tmgross@umich.edu>,
"Masahiro Yamada" <masahiroy@kernel.org>,
"Nathan Chancellor" <nathan@kernel.org>,
"Nicolas Schier" <nicolas@fjasle.eu>,
"Luis Chamberlain" <mcgrof@kernel.org>,
rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org,
"Adam Bratschi-Kaye" <ark.email@gmail.com>,
linux-kbuild@vger.kernel.org, "Petr Pavlu" <petr.pavlu@suse.com>,
"Sami Tolvanen" <samitolvanen@google.com>,
"Daniel Gomez" <da.gomez@samsung.com>,
"Simona Vetter" <simona.vetter@ffwll.ch>,
"Greg KH" <gregkh@linuxfoundation.org>,
linux-modules@vger.kernel.org
Subject: Re: [PATCH v7 6/6] rust: add parameter support to the `module!` macro
Date: Tue, 25 Feb 2025 16:35:02 +0100 [thread overview]
Message-ID: <87wmdeujfd.fsf@kernel.org> (raw)
In-Reply-To: <20250225151417.7805b697@eugeo> (Gary Guo's message of "Tue, 25 Feb 2025 15:14:17 +0000")
"Gary Guo" <gary@garyguo.net> writes:
> On Tue, 18 Feb 2025 14:00:48 +0100
> Andreas Hindborg <a.hindborg@kernel.org> wrote:
>
>> This patch includes changes required for Rust kernel modules to utilize
>> module parameters. This code implements read only support for integer
>> types without `sysfs` support.
>>
>> Signed-off-by: Andreas Hindborg <a.hindborg@kernel.org>
>> Acked-by: Petr Pavlu <petr.pavlu@suse.com> # from modules perspective
>> ---
>> rust/kernel/lib.rs | 1 +
>> rust/kernel/module_param.rs | 226 +++++++++++++++++++++++++++++++++++++++++++
>> rust/macros/helpers.rs | 25 +++++
>> rust/macros/lib.rs | 31 ++++++
>> rust/macros/module.rs | 191 ++++++++++++++++++++++++++++++++----
>> samples/rust/rust_minimal.rs | 10 ++
>> 6 files changed, 466 insertions(+), 18 deletions(-)
>>
>> diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs
>> index 496ed32b0911a..aec04df2bac9f 100644
>> --- a/rust/kernel/lib.rs
>> +++ b/rust/kernel/lib.rs
>> @@ -57,6 +57,7 @@
>> pub mod kunit;
>> pub mod list;
>> pub mod miscdevice;
>> +pub mod module_param;
>> #[cfg(CONFIG_NET)]
>> pub mod net;
>> pub mod of;
>> diff --git a/rust/kernel/module_param.rs b/rust/kernel/module_param.rs
>> new file mode 100644
>> index 0000000000000..0047126c917f4
>> --- /dev/null
>> +++ b/rust/kernel/module_param.rs
>> @@ -0,0 +1,226 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +
>> +//! Types for module parameters.
>> +//!
>> +//! C header: [`include/linux/moduleparam.h`](srctree/include/linux/moduleparam.h)
>> +
>> +use crate::prelude::*;
>> +use crate::str::BStr;
>> +
>> +/// Newtype to make `bindings::kernel_param` [`Sync`].
>> +#[repr(transparent)]
>> +#[doc(hidden)]
>> +pub struct RacyKernelParam(pub ::kernel::bindings::kernel_param);
>> +
>> +// SAFETY: C kernel handles serializing access to this type. We never access
>> +// from Rust module.
>> +unsafe impl Sync for RacyKernelParam {}
>
> I wonder if we should have a custom impl of `SyncUnsafeCell` for this
> kind of usage (so that when it is stabilized by Rust, we can just switc
> over).
We discussed this before, I don't recall what we decided. At any rate,
it's orthogonal. We can patch this if we add `SyncUnsafeCell`.
>
>> +
>> +/// Types that can be used for module parameters.
>> +///
>> +/// Note that displaying the type in `sysfs` will fail if
>> +/// [`Display`](core::fmt::Display) implementation would write more than
>> +/// [`PAGE_SIZE`] - 1 bytes.
>> +///
>> +/// [`PAGE_SIZE`]: `bindings::PAGE_SIZE`
>> +pub trait ModuleParam: Sized {
>> + /// The [`ModuleParam`] will be used by the kernel module through this type.
>> + ///
>> + /// This may differ from `Self` if, for example, `Self` needs to track
>> + /// ownership without exposing it or allocate extra space for other possible
>> + /// parameter values.
>> + // This is required to support string parameters in the future.
>> + type Value: ?Sized;
>> +
>> + /// Parse a parameter argument into the parameter value.
>> + ///
>> + /// `Err(_)` should be returned when parsing of the argument fails.
>> + ///
>> + /// Parameters passed at boot time will be set before [`kmalloc`] is
>> + /// available (even if the module is loaded at a later time). However, in
>> + /// this case, the argument buffer will be valid for the entire lifetime of
>> + /// the kernel. So implementations of this method which need to allocate
>> + /// should first check that the allocator is available (with
>> + /// [`crate::bindings::slab_is_available`]) and when it is not available
>> + /// provide an alternative implementation which doesn't allocate. In cases
>> + /// where the allocator is not available it is safe to save references to
>> + /// `arg` in `Self`, but in other cases a copy should be made.
>> + ///
>> + /// [`kmalloc`]: srctree/include/linux/slab.h
>> + fn try_from_param_arg(arg: &'static [u8]) -> Result<Self>;
>> +}
>> +
>> +/// Set the module parameter from a string.
>> +///
>> +/// Used to set the parameter value at kernel initialization, when loading
>> +/// the module or when set through `sysfs`.
>> +///
>> +/// `param.arg` is a pointer to `*mut T` as set up by the [`module!`]
>> +/// macro.
>> +///
>> +/// See `struct kernel_param_ops.set`.
>> +///
>> +/// # Safety
>> +///
>> +/// If `val` is non-null then it must point to a valid null-terminated
>> +/// string. The `arg` field of `param` must be an instance of `T`.
>> +///
>> +/// # Invariants
>> +///
>> +/// Currently, we only support read-only parameters that are not readable
>> +/// from `sysfs`. Thus, this function is only called at kernel
>> +/// initialization time, or at module load time, and we have exclusive
>> +/// access to the parameter for the duration of the function.
>> +///
>> +/// [`module!`]: macros::module
>> +unsafe extern "C" fn set_param<T>(
>> + val: *const kernel::ffi::c_char,
>> + param: *const crate::bindings::kernel_param,
>> +) -> core::ffi::c_int
>> +where
>> + T: ModuleParam,
>> +{
>> + // NOTE: If we start supporting arguments without values, val _is_ allowed
>> + // to be null here.
>> + if val.is_null() {
>> + // TODO: Use pr_warn_once available.
>> + crate::pr_warn!("Null pointer passed to `module_param::set_param`");
>> + return crate::error::code::EINVAL.to_errno();
>
> This is already in prelude, so you can just use `EINVAL` directly.
Thanks.
>
>> + }
>> +
>> + // SAFETY: By function safety requirement, val is non-null and
>> + // null-terminated. By C API contract, `val` is live and valid for reads
>> + // for the duration of this function.
>> + let arg = unsafe { CStr::from_char_ptr(val).as_bytes() };
>> +
>> + crate::error::from_result(|| {
>> + let new_value = T::try_from_param_arg(arg)?;
>> +
>> + // SAFETY: `param` is guaranteed to be valid by C API contract
>> + // and `arg` is guaranteed to point to an instance of `T`.
>> + let old_value = unsafe { (*param).__bindgen_anon_1.arg as *mut T };
>> +
>> + // SAFETY: `old_value` is valid for writes, as we have exclusive
>> + // access. `old_value` is pointing to an initialized static, and
>> + // so it is properly initialized.
>> + unsafe { core::ptr::replace(old_value, new_value) };
>> + Ok(0)
>> + })
>> +}
>> +
>> +/// Drop the parameter.
>> +///
>> +/// Called when unloading a module.
>> +///
>> +/// # Safety
>> +///
>> +/// The `arg` field of `param` must be an initialized instance of `T`.
>> +unsafe extern "C" fn free<T>(arg: *mut core::ffi::c_void)
>> +where
>> + T: ModuleParam,
>> +{
>> + // SAFETY: By function safety requirement, `arg` is an initialized
>> + // instance of `T`. By C API contract, `arg` will not be used after
>> + // this function returns.
>> + unsafe { core::ptr::drop_in_place(arg as *mut T) };
>> +}
>> +
>> +macro_rules! impl_int_module_param {
>> + ($ty:ident) => {
>> + impl ModuleParam for $ty {
>> + type Value = $ty;
>> +
>> + fn try_from_param_arg(arg: &'static [u8]) -> Result<Self> {
>> + let bstr = BStr::from_bytes(arg);
>
> Why isn't `arg` BStr in the first place?
I'll change it.
Best regards,
Andreas Hindborg
next prev parent reply other threads:[~2025-02-25 15:35 UTC|newest]
Thread overview: 31+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <JKqjFnoTeEbURcTQ5PpmUZWDS2VMEt0eZl68dWkgk3e8ROFpb2eTWH2mStKkkXJw__Ql5DdYvIR9I7qYks-lag==@protonmail.internalid>
2025-02-18 13:00 ` [PATCH v7 0/6] rust: extend `module!` macro with integer parameter support Andreas Hindborg
2025-02-18 13:00 ` [PATCH v7 1/6] rust: str: implement `PartialEq` for `BStr` Andreas Hindborg
2025-02-21 15:51 ` Daniel Almeida
2025-02-18 13:00 ` [PATCH v7 2/6] rust: str: implement `Index` " Andreas Hindborg
2025-02-21 15:58 ` Daniel Almeida
2025-02-24 13:50 ` Fiona Behrens
2025-02-18 13:00 ` [PATCH v7 3/6] rust: str: implement `AsRef<BStr>` for `[u8]` and `BStr` Andreas Hindborg
2025-02-21 16:01 ` Daniel Almeida
2025-02-21 16:15 ` Daniel Almeida
2025-02-21 18:52 ` Gary Guo
2025-02-18 13:00 ` [PATCH v7 4/6] rust: str: implement `strip_prefix` for `BStr` Andreas Hindborg
2025-02-21 16:14 ` Daniel Almeida
2025-02-18 13:00 ` [PATCH v7 5/6] rust: str: add radix prefixed integer parsing functions Andreas Hindborg
2025-02-24 13:34 ` Daniel Almeida
2025-02-24 13:43 ` Andreas Hindborg
2025-02-24 22:30 ` Janne Grunau
2025-02-25 1:51 ` Miguel Ojeda
2025-02-25 8:07 ` Andreas Hindborg
2025-02-25 5:54 ` Andreas Hindborg
2025-02-18 13:00 ` [PATCH v7 6/6] rust: add parameter support to the `module!` macro Andreas Hindborg
2025-02-24 15:28 ` Daniel Almeida
2025-02-25 8:02 ` Andreas Hindborg
2025-02-25 15:14 ` Gary Guo
2025-02-25 15:35 ` Andreas Hindborg [this message]
2025-02-21 15:45 ` [PATCH v7 0/6] rust: extend `module!` macro with integer parameter support Daniel Almeida
2025-02-22 8:49 ` Andreas Hindborg
2025-02-24 11:27 ` Andreas Hindborg
2025-02-25 10:22 ` Petr Pavlu
2025-02-25 11:54 ` Miguel Ojeda
2025-02-27 14:55 ` Petr Pavlu
2025-02-27 15:37 ` Miguel Ojeda
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=87wmdeujfd.fsf@kernel.org \
--to=a.hindborg@kernel.org \
--cc=alex.gaynor@gmail.com \
--cc=aliceryhl@google.com \
--cc=ark.email@gmail.com \
--cc=benno.lossin@proton.me \
--cc=bjorn3_gh@protonmail.com \
--cc=boqun.feng@gmail.com \
--cc=da.gomez@samsung.com \
--cc=gary@garyguo.net \
--cc=gregkh@linuxfoundation.org \
--cc=linux-kbuild@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-modules@vger.kernel.org \
--cc=masahiroy@kernel.org \
--cc=mcgrof@kernel.org \
--cc=nathan@kernel.org \
--cc=nicolas@fjasle.eu \
--cc=ojeda@kernel.org \
--cc=petr.pavlu@suse.com \
--cc=rust-for-linux@vger.kernel.org \
--cc=samitolvanen@google.com \
--cc=simona.vetter@ffwll.ch \
--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.