From: Gary Guo <gary@garyguo.net>
To: Danilo Krummrich <dakr@kernel.org>
Cc: gregkh@linuxfoundation.org, rafael@kernel.org,
bhelgaas@google.com, ojeda@kernel.org, alex.gaynor@gmail.com,
boqun.feng@gmail.com, bjorn3_gh@protonmail.com,
benno.lossin@proton.me, tmgross@umich.edu,
a.hindborg@samsung.com, aliceryhl@google.com, airlied@gmail.com,
fujita.tomonori@gmail.com, lina@asahilina.net,
pstanner@redhat.com, ajanulgu@redhat.com, lyude@redhat.com,
robh@kernel.org, daniel.almeida@collabora.com,
saravanak@google.com, dirk.behme@de.bosch.com, j@jannau.net,
fabien.parent@linaro.org, chrisi.schrefl@gmail.com,
paulmck@kernel.org, rust-for-linux@vger.kernel.org,
linux-kernel@vger.kernel.org, linux-pci@vger.kernel.org,
devicetree@vger.kernel.org, rcu@vger.kernel.org,
Wedson Almeida Filho <wedsonaf@gmail.com>
Subject: Re: [PATCH v7 02/16] rust: implement generic driver registration
Date: Tue, 24 Dec 2024 19:58:21 +0000 [thread overview]
Message-ID: <20241224195821.3b43302b.gary@garyguo.net> (raw)
In-Reply-To: <20241219170425.12036-3-dakr@kernel.org>
On Thu, 19 Dec 2024 18:04:04 +0100
Danilo Krummrich <dakr@kernel.org> wrote:
> Implement the generic `Registration` type and the `RegistrationOps`
> trait.
>
> The `Registration` structure is the common type that represents a driver
> registration and is typically bound to the lifetime of a module. However,
> it doesn't implement actual calls to the kernel's driver core to register
> drivers itself.
>
> Instead the `RegistrationOps` trait is provided to subsystems, which have
> to implement `RegistrationOps::register` and
> `RegistrationOps::unregister`. Subsystems have to provide an
> implementation for both of those methods where the subsystem specific
> variants to register / unregister a driver have to implemented.
>
> For instance, the PCI subsystem would call __pci_register_driver() from
> `RegistrationOps::register` and pci_unregister_driver() from
> `DrvierOps::unregister`.
>
> Co-developed-by: Wedson Almeida Filho <wedsonaf@gmail.com>
> Signed-off-by: Wedson Almeida Filho <wedsonaf@gmail.com>
> Signed-off-by: Danilo Krummrich <dakr@kernel.org>
Hi Danilo,
I think there're soundness issues with this API, please see comments
inlined below.
Best,
Gary
> ---
> MAINTAINERS | 1 +
> rust/kernel/driver.rs | 117 ++++++++++++++++++++++++++++++++++++++++++
> rust/kernel/lib.rs | 1 +
> 3 files changed, 119 insertions(+)
> create mode 100644 rust/kernel/driver.rs
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index baf0eeb9a355..2ad58ed40079 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -7033,6 +7033,7 @@ F: include/linux/kobj*
> F: include/linux/property.h
> F: lib/kobj*
> F: rust/kernel/device.rs
> +F: rust/kernel/driver.rs
>
> DRIVERS FOR OMAP ADAPTIVE VOLTAGE SCALING (AVS)
> M: Nishanth Menon <nm@ti.com>
> diff --git a/rust/kernel/driver.rs b/rust/kernel/driver.rs
> new file mode 100644
> index 000000000000..c1957ee7bb7e
> --- /dev/null
> +++ b/rust/kernel/driver.rs
> @@ -0,0 +1,117 @@
> +// SPDX-License-Identifier: GPL-2.0
> +
> +//! Generic support for drivers of different buses (e.g., PCI, Platform, Amba, etc.).
> +//!
> +//! Each bus / subsystem is expected to implement [`RegistrationOps`], which allows drivers to
> +//! register using the [`Registration`] class.
> +
> +use crate::error::{Error, Result};
> +use crate::{init::PinInit, str::CStr, try_pin_init, types::Opaque, ThisModule};
> +use core::pin::Pin;
> +use macros::{pin_data, pinned_drop};
> +
> +/// The [`RegistrationOps`] trait serves as generic interface for subsystems (e.g., PCI, Platform,
> +/// Amba, etc.) to provide the corresponding subsystem specific implementation to register /
> +/// unregister a driver of the particular type (`RegType`).
> +///
> +/// For instance, the PCI subsystem would set `RegType` to `bindings::pci_driver` and call
> +/// `bindings::__pci_register_driver` from `RegistrationOps::register` and
> +/// `bindings::pci_unregister_driver` from `RegistrationOps::unregister`.
> +pub trait RegistrationOps {
> + /// The type that holds information about the registration. This is typically a struct defined
> + /// by the C portion of the kernel.
> + type RegType: Default;
> +
> + /// Registers a driver.
> + ///
> + /// On success, `reg` must remain pinned and valid until the matching call to
> + /// [`RegistrationOps::unregister`].
This looks like an obligation for the caller, so this function should
be unsafe?
> + fn register(
> + reg: &Opaque<Self::RegType>,
> + name: &'static CStr,
> + module: &'static ThisModule,
> + ) -> Result;
> +
> + /// Unregisters a driver previously registered with [`RegistrationOps::register`].
Similarly this is an obligation for the caller.
> + fn unregister(reg: &Opaque<Self::RegType>);
> +}
> +
> +/// A [`Registration`] is a generic type that represents the registration of some driver type (e.g.
> +/// `bindings::pci_driver`). Therefore a [`Registration`] must be initialized with a type that
> +/// implements the [`RegistrationOps`] trait, such that the generic `T::register` and
> +/// `T::unregister` calls result in the subsystem specific registration calls.
> +///
> +///Once the `Registration` structure is dropped, the driver is unregistered.
> +#[pin_data(PinnedDrop)]
> +pub struct Registration<T: RegistrationOps> {
> + #[pin]
> + reg: Opaque<T::RegType>,
> +}
> +
> +// SAFETY: `Registration` has no fields or methods accessible via `&Registration`, so it is safe to
> +// share references to it with multiple threads as nothing can be done.
> +unsafe impl<T: RegistrationOps> Sync for Registration<T> {}
> +
> +// SAFETY: Both registration and unregistration are implemented in C and safe to be performed from
> +// any thread, so `Registration` is `Send`.
> +unsafe impl<T: RegistrationOps> Send for Registration<T> {}
> +
> +impl<T: RegistrationOps> Registration<T> {
> + /// Creates a new instance of the registration object.
> + pub fn new(name: &'static CStr, module: &'static ThisModule) -> impl PinInit<Self, Error> {
> + try_pin_init!(Self {
> + reg <- Opaque::try_ffi_init(|ptr: *mut T::RegType| {
> + // SAFETY: `try_ffi_init` guarantees that `ptr` is valid for write.
> + unsafe { ptr.write(T::RegType::default()) };
Any reason that this is initialised with a default, and not be up to
`T::register` to initialise?
> +
> + // SAFETY: `try_ffi_init` guarantees that `ptr` is valid for write, and it has
> + // just been initialised above, so it's also valid for read.
Opaque can hold uninitialised value so as long as `ptr` is not dangling
this is fine. There's no need to actually initialise.
> + let drv = unsafe { &*(ptr as *const Opaque<T::RegType>) };
> +
> + T::register(drv, name, module)
> + }),
> + })
> + }
> +}
> +
> +#[pinned_drop]
> +impl<T: RegistrationOps> PinnedDrop for Registration<T> {
> + fn drop(self: Pin<&mut Self>) {
> + T::unregister(&self.reg);
> + }
> +}
> +
> +/// Declares a kernel module that exposes a single driver.
> +///
> +/// It is meant to be used as a helper by other subsystems so they can more easily expose their own
> +/// macros.
> +#[macro_export]
I think this is supposed to be used by other macros only? If so, please
add `#[doc(hidden)]`.
> +macro_rules! module_driver {
> + (<$gen_type:ident>, $driver_ops:ty, { type: $type:ty, $($f:tt)* }) => {
> + type Ops<$gen_type> = $driver_ops;
> +
> + #[$crate::prelude::pin_data]
> + struct DriverModule {
> + #[pin]
> + _driver: $crate::driver::Registration<Ops<$type>>,
> + }
> +
> + impl $crate::InPlaceModule for DriverModule {
> + fn init(
> + module: &'static $crate::ThisModule
> + ) -> impl $crate::init::PinInit<Self, $crate::error::Error> {
> + $crate::try_pin_init!(Self {
> + _driver <- $crate::driver::Registration::new(
> + <Self as $crate::ModuleMetadata>::NAME,
> + module,
> + ),
> + })
> + }
> + }
> +
> + $crate::prelude::module! {
> + type: DriverModule,
> + $($f)*
> + }
> + }
> +}
> diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs
> index 61b82b78b915..7818407f9aac 100644
> --- a/rust/kernel/lib.rs
> +++ b/rust/kernel/lib.rs
> @@ -35,6 +35,7 @@
> mod build_assert;
> pub mod cred;
> pub mod device;
> +pub mod driver;
> pub mod error;
> #[cfg(CONFIG_RUST_FW_LOADER_ABSTRACTIONS)]
> pub mod firmware;
next prev parent reply other threads:[~2024-12-24 19:58 UTC|newest]
Thread overview: 47+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-12-19 17:04 [PATCH v7 00/16] Device / Driver PCI / Platform Rust abstractions Danilo Krummrich
2024-12-19 17:04 ` [PATCH v7 01/16] rust: module: add trait `ModuleMetadata` Danilo Krummrich
2024-12-24 20:51 ` Gary Guo
2024-12-19 17:04 ` [PATCH v7 02/16] rust: implement generic driver registration Danilo Krummrich
2024-12-24 19:58 ` Gary Guo [this message]
2025-01-02 9:34 ` Danilo Krummrich
2024-12-19 17:04 ` [PATCH v7 03/16] rust: implement `IdArray`, `IdTable` and `RawDeviceId` Danilo Krummrich
2024-12-24 20:10 ` Gary Guo
2025-01-02 9:36 ` Danilo Krummrich
2025-03-15 16:52 ` Tamir Duberstein
2025-03-15 16:59 ` Danilo Krummrich
2025-03-15 17:31 ` Tamir Duberstein
2024-12-19 17:04 ` [PATCH v7 04/16] rust: add rcu abstraction Danilo Krummrich
2024-12-24 20:54 ` Gary Guo
2025-01-02 9:44 ` Danilo Krummrich
2024-12-19 17:04 ` [PATCH v7 05/16] rust: types: add `Opaque::pin_init` Danilo Krummrich
2024-12-24 20:21 ` Gary Guo
2024-12-19 17:04 ` [PATCH v7 06/16] rust: add `Revocable` type Danilo Krummrich
2024-12-19 17:04 ` [PATCH v7 07/16] rust: add `io::{Io, IoRaw}` base types Danilo Krummrich
2025-01-16 10:31 ` Fiona Behrens
2025-01-20 12:54 ` Danilo Krummrich
2025-02-21 1:20 ` Alistair Popple
2025-02-21 3:58 ` Miguel Ojeda
2025-02-25 5:50 ` Alistair Popple
2025-02-25 11:04 ` Danilo Krummrich
2025-02-27 0:25 ` Alistair Popple
2025-02-27 10:01 ` Danilo Krummrich
2025-02-28 5:29 ` Alistair Popple
2025-02-28 10:12 ` Danilo Krummrich
2025-02-28 10:22 ` Miguel Ojeda
2025-02-27 16:06 ` Miguel Ojeda
2024-12-19 17:04 ` [PATCH v7 08/16] rust: add devres abstraction Danilo Krummrich
2024-12-24 21:53 ` Gary Guo
2025-01-02 10:30 ` Danilo Krummrich
2025-01-02 15:59 ` Danilo Krummrich
2025-01-14 16:33 ` Danilo Krummrich
2025-01-15 6:41 ` Danilo Krummrich
2024-12-19 17:04 ` [PATCH v7 09/16] rust: pci: add basic PCI device / driver abstractions Danilo Krummrich
2024-12-19 17:04 ` [PATCH v7 10/16] rust: pci: implement I/O mappable `pci::Bar` Danilo Krummrich
2024-12-19 17:04 ` [PATCH v7 11/16] samples: rust: add Rust PCI sample driver Danilo Krummrich
2024-12-19 17:04 ` [PATCH v7 12/16] rust: of: add `of::DeviceId` abstraction Danilo Krummrich
2024-12-19 17:04 ` [PATCH v7 13/16] rust: driver: implement `Adapter` Danilo Krummrich
2024-12-19 17:04 ` [PATCH v7 14/16] rust: platform: add basic platform device / driver abstractions Danilo Krummrich
2024-12-19 17:04 ` [PATCH v7 15/16] samples: rust: add Rust platform sample driver Danilo Krummrich
2024-12-19 17:04 ` [PATCH v7 16/16] MAINTAINERS: add Danilo to DRIVER CORE Danilo Krummrich
2024-12-20 7:24 ` [PATCH v7 00/16] Device / Driver PCI / Platform Rust abstractions Dirk Behme
2024-12-20 16:44 ` Greg KH
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=20241224195821.3b43302b.gary@garyguo.net \
--to=gary@garyguo.net \
--cc=a.hindborg@samsung.com \
--cc=airlied@gmail.com \
--cc=ajanulgu@redhat.com \
--cc=alex.gaynor@gmail.com \
--cc=aliceryhl@google.com \
--cc=benno.lossin@proton.me \
--cc=bhelgaas@google.com \
--cc=bjorn3_gh@protonmail.com \
--cc=boqun.feng@gmail.com \
--cc=chrisi.schrefl@gmail.com \
--cc=dakr@kernel.org \
--cc=daniel.almeida@collabora.com \
--cc=devicetree@vger.kernel.org \
--cc=dirk.behme@de.bosch.com \
--cc=fabien.parent@linaro.org \
--cc=fujita.tomonori@gmail.com \
--cc=gregkh@linuxfoundation.org \
--cc=j@jannau.net \
--cc=lina@asahilina.net \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-pci@vger.kernel.org \
--cc=lyude@redhat.com \
--cc=ojeda@kernel.org \
--cc=paulmck@kernel.org \
--cc=pstanner@redhat.com \
--cc=rafael@kernel.org \
--cc=rcu@vger.kernel.org \
--cc=robh@kernel.org \
--cc=rust-for-linux@vger.kernel.org \
--cc=saravanak@google.com \
--cc=tmgross@umich.edu \
--cc=wedsonaf@gmail.com \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox