Commit 7f15c46a authored by Wedson Almeida Filho's avatar Wedson Almeida Filho Committed by Greg Kroah-Hartman
Browse files

rust: introduce `InPlaceModule`



This allows modules to be initialised in-place in pinned memory, which
enables the usage of pinned types (e.g., mutexes, spinlocks, driver
registrations, etc.) in modules without any extra allocations.

Signed-off-by: default avatarWedson Almeida Filho <walmeida@microsoft.com>
Signed-off-by: default avatarDanilo Krummrich <dakr@kernel.org>
Acked-by: default avatarMiguel Ojeda <ojeda@kernel.org>
Link: https://lore.kernel.org/r/20241022213221.2383-3-dakr@kernel.org


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 77e83550
Loading
Loading
Loading
Loading
+23 −0
Original line number Diff line number Diff line
@@ -82,6 +82,29 @@ pub trait Module: Sized + Sync + Send {
    fn init(module: &'static ThisModule) -> error::Result<Self>;
}

/// A module that is pinned and initialised in-place.
pub trait InPlaceModule: Sync + Send {
    /// Creates an initialiser for the module.
    ///
    /// It is called when the module is loaded.
    fn init(module: &'static ThisModule) -> impl init::PinInit<Self, error::Error>;
}

impl<T: Module> InPlaceModule for T {
    fn init(module: &'static ThisModule) -> impl init::PinInit<Self, error::Error> {
        let initer = move |slot: *mut Self| {
            let m = <Self as Module>::init(module)?;

            // SAFETY: `slot` is valid for write per the contract with `pin_init_from_closure`.
            unsafe { slot.write(m) };
            Ok(())
        };

        // SAFETY: On success, `initer` always fully initialises an instance of `Self`.
        unsafe { init::pin_init_from_closure(initer) }
    }
}

/// Equivalent to `THIS_MODULE` in the C API.
///
/// C header: [`include/linux/export.h`](srctree/include/linux/export.h)
+12 −16
Original line number Diff line number Diff line
@@ -232,6 +232,7 @@ pub(crate) fn module(ts: TokenStream) -> TokenStream {
            mod __module_init {{
                mod __module_init {{
                    use super::super::{type_};
                    use kernel::init::PinInit;

                    /// The \"Rust loadable module\" mark.
                    //
@@ -242,7 +243,8 @@ mod __module_init {{
                    #[used]
                    static __IS_RUST_MODULE: () = ();

                    static mut __MOD: Option<{type_}> = None;
                    static mut __MOD: core::mem::MaybeUninit<{type_}> =
                        core::mem::MaybeUninit::uninit();

                    // Loadable modules need to export the `{{init,cleanup}}_module` identifiers.
                    /// # Safety
@@ -331,20 +333,14 @@ mod __module_init {{
                    ///
                    /// This function must only be called once.
                    unsafe fn __init() -> core::ffi::c_int {{
                        match <{type_} as kernel::Module>::init(&super::super::THIS_MODULE) {{
                            Ok(m) => {{
                                // SAFETY: No data race, since `__MOD` can only be accessed by this
                                // module and there only `__init` and `__exit` access it. These
                                // functions are only called once and `__exit` cannot be called
                                // before or during `__init`.
                                unsafe {{
                                    __MOD = Some(m);
                                }}
                                return 0;
                            }}
                            Err(e) => {{
                                return e.to_errno();
                            }}
                        let initer =
                            <{type_} as kernel::InPlaceModule>::init(&super::super::THIS_MODULE);
                        // SAFETY: No data race, since `__MOD` can only be accessed by this module
                        // and there only `__init` and `__exit` access it. These functions are only
                        // called once and `__exit` cannot be called before or during `__init`.
                        match unsafe {{ initer.__pinned_init(__MOD.as_mut_ptr()) }} {{
                            Ok(m) => 0,
                            Err(e) => e.to_errno(),
                        }}
                    }}

@@ -359,7 +355,7 @@ unsafe fn __exit() {{
                        // called once and `__init` was already called.
                        unsafe {{
                            // Invokes `drop()` on `__MOD`, which should be used for cleanup.
                            __MOD = None;
                            __MOD.assume_init_drop();
                        }}
                    }}