xref: /linux-6.15/rust/kernel/init.rs (revision dbd5058b)
186f7dacaSBenno Lossin // SPDX-License-Identifier: GPL-2.0
286f7dacaSBenno Lossin 
386f7dacaSBenno Lossin //! Extensions to the [`pin-init`] crate.
486f7dacaSBenno Lossin //!
586f7dacaSBenno Lossin //! Most `struct`s from the [`sync`] module need to be pinned, because they contain self-referential
686f7dacaSBenno Lossin //! `struct`s from C. [Pinning][pinning] is Rust's way of ensuring data does not move.
786f7dacaSBenno Lossin //!
886f7dacaSBenno Lossin //! The [`pin-init`] crate is the way such structs are initialized on the Rust side. Please refer
986f7dacaSBenno Lossin //! to its documentation to better understand how to use it. Additionally, there are many examples
1086f7dacaSBenno Lossin //! throughout the kernel, such as the types from the [`sync`] module. And the ones presented
1186f7dacaSBenno Lossin //! below.
1286f7dacaSBenno Lossin //!
1386f7dacaSBenno Lossin //! [`sync`]: crate::sync
1486f7dacaSBenno Lossin //! [pinning]: https://doc.rust-lang.org/std/pin/index.html
1586f7dacaSBenno Lossin //! [`pin-init`]: https://rust.docs.kernel.org/pin_init/
1686f7dacaSBenno Lossin //!
1786f7dacaSBenno Lossin //! # [`Opaque<T>`]
1886f7dacaSBenno Lossin //!
1986f7dacaSBenno Lossin //! For the special case where initializing a field is a single FFI-function call that cannot fail,
2086f7dacaSBenno Lossin //! there exist the helper function [`Opaque::ffi_init`]. This function initialize a single
2186f7dacaSBenno Lossin //! [`Opaque<T>`] field by just delegating to the supplied closure. You can use these in
2286f7dacaSBenno Lossin //! combination with [`pin_init!`].
2386f7dacaSBenno Lossin //!
2486f7dacaSBenno Lossin //! [`Opaque<T>`]: crate::types::Opaque
2586f7dacaSBenno Lossin //! [`Opaque::ffi_init`]: crate::types::Opaque::ffi_init
26*dbd5058bSBenno Lossin //! [`pin_init!`]: pin_init::pin_init
2786f7dacaSBenno Lossin //!
2886f7dacaSBenno Lossin //! # Examples
2986f7dacaSBenno Lossin //!
3086f7dacaSBenno Lossin //! ## General Examples
3186f7dacaSBenno Lossin //!
3286f7dacaSBenno Lossin //! ```rust,ignore
3386f7dacaSBenno Lossin //! # #![allow(clippy::disallowed_names)]
3486f7dacaSBenno Lossin //! use kernel::types::Opaque;
3586f7dacaSBenno Lossin //! use pin_init::pin_init_from_closure;
3686f7dacaSBenno Lossin //!
3786f7dacaSBenno Lossin //! // assume we have some `raw_foo` type in C:
3886f7dacaSBenno Lossin //! #[repr(C)]
3986f7dacaSBenno Lossin //! struct RawFoo([u8; 16]);
4086f7dacaSBenno Lossin //! extern {
4186f7dacaSBenno Lossin //!     fn init_foo(_: *mut RawFoo);
4286f7dacaSBenno Lossin //! }
4386f7dacaSBenno Lossin //!
4486f7dacaSBenno Lossin //! #[pin_data]
4586f7dacaSBenno Lossin //! struct Foo {
4686f7dacaSBenno Lossin //!     #[pin]
4786f7dacaSBenno Lossin //!     raw: Opaque<RawFoo>,
4886f7dacaSBenno Lossin //! }
4986f7dacaSBenno Lossin //!
5086f7dacaSBenno Lossin //! impl Foo {
5186f7dacaSBenno Lossin //!     fn setup(self: Pin<&mut Self>) {
5286f7dacaSBenno Lossin //!         pr_info!("Setting up foo\n");
5386f7dacaSBenno Lossin //!     }
5486f7dacaSBenno Lossin //! }
5586f7dacaSBenno Lossin //!
5686f7dacaSBenno Lossin //! let foo = pin_init!(Foo {
5786f7dacaSBenno Lossin //!     raw <- unsafe {
5886f7dacaSBenno Lossin //!         Opaque::ffi_init(|s| {
5986f7dacaSBenno Lossin //!             // note that this cannot fail.
6086f7dacaSBenno Lossin //!             init_foo(s);
6186f7dacaSBenno Lossin //!         })
6286f7dacaSBenno Lossin //!     },
6386f7dacaSBenno Lossin //! }).pin_chain(|foo| {
6486f7dacaSBenno Lossin //!     foo.setup();
6586f7dacaSBenno Lossin //!     Ok(())
6686f7dacaSBenno Lossin //! });
6786f7dacaSBenno Lossin //! ```
6886f7dacaSBenno Lossin //!
6986f7dacaSBenno Lossin //! ```rust,ignore
7086f7dacaSBenno Lossin //! # #![allow(unreachable_pub, clippy::disallowed_names)]
7186f7dacaSBenno Lossin //! use kernel::{prelude::*, types::Opaque};
7286f7dacaSBenno Lossin //! use core::{ptr::addr_of_mut, marker::PhantomPinned, pin::Pin};
7386f7dacaSBenno Lossin //! # mod bindings {
7486f7dacaSBenno Lossin //! #     #![allow(non_camel_case_types)]
7586f7dacaSBenno Lossin //! #     pub struct foo;
7686f7dacaSBenno Lossin //! #     pub unsafe fn init_foo(_ptr: *mut foo) {}
7786f7dacaSBenno Lossin //! #     pub unsafe fn destroy_foo(_ptr: *mut foo) {}
7886f7dacaSBenno Lossin //! #     pub unsafe fn enable_foo(_ptr: *mut foo, _flags: u32) -> i32 { 0 }
7986f7dacaSBenno Lossin //! # }
8086f7dacaSBenno Lossin //! # // `Error::from_errno` is `pub(crate)` in the `kernel` crate, thus provide a workaround.
8186f7dacaSBenno Lossin //! # trait FromErrno {
8286f7dacaSBenno Lossin //! #     fn from_errno(errno: core::ffi::c_int) -> Error {
8386f7dacaSBenno Lossin //! #         // Dummy error that can be constructed outside the `kernel` crate.
8486f7dacaSBenno Lossin //! #         Error::from(core::fmt::Error)
8586f7dacaSBenno Lossin //! #     }
8686f7dacaSBenno Lossin //! # }
8786f7dacaSBenno Lossin //! # impl FromErrno for Error {}
8886f7dacaSBenno Lossin //! /// # Invariants
8986f7dacaSBenno Lossin //! ///
9086f7dacaSBenno Lossin //! /// `foo` is always initialized
9186f7dacaSBenno Lossin //! #[pin_data(PinnedDrop)]
9286f7dacaSBenno Lossin //! pub struct RawFoo {
9386f7dacaSBenno Lossin //!     #[pin]
9486f7dacaSBenno Lossin //!     foo: Opaque<bindings::foo>,
9586f7dacaSBenno Lossin //!     #[pin]
9686f7dacaSBenno Lossin //!     _p: PhantomPinned,
9786f7dacaSBenno Lossin //! }
9886f7dacaSBenno Lossin //!
9986f7dacaSBenno Lossin //! impl RawFoo {
10086f7dacaSBenno Lossin //!     pub fn new(flags: u32) -> impl PinInit<Self, Error> {
10186f7dacaSBenno Lossin //!         // SAFETY:
10286f7dacaSBenno Lossin //!         // - when the closure returns `Ok(())`, then it has successfully initialized and
10386f7dacaSBenno Lossin //!         //   enabled `foo`,
10486f7dacaSBenno Lossin //!         // - when it returns `Err(e)`, then it has cleaned up before
10586f7dacaSBenno Lossin //!         unsafe {
10686f7dacaSBenno Lossin //!             pin_init::pin_init_from_closure(move |slot: *mut Self| {
10786f7dacaSBenno Lossin //!                 // `slot` contains uninit memory, avoid creating a reference.
10886f7dacaSBenno Lossin //!                 let foo = addr_of_mut!((*slot).foo);
10986f7dacaSBenno Lossin //!
11086f7dacaSBenno Lossin //!                 // Initialize the `foo`
11186f7dacaSBenno Lossin //!                 bindings::init_foo(Opaque::raw_get(foo));
11286f7dacaSBenno Lossin //!
11386f7dacaSBenno Lossin //!                 // Try to enable it.
11486f7dacaSBenno Lossin //!                 let err = bindings::enable_foo(Opaque::raw_get(foo), flags);
11586f7dacaSBenno Lossin //!                 if err != 0 {
11686f7dacaSBenno Lossin //!                     // Enabling has failed, first clean up the foo and then return the error.
11786f7dacaSBenno Lossin //!                     bindings::destroy_foo(Opaque::raw_get(foo));
11886f7dacaSBenno Lossin //!                     return Err(Error::from_errno(err));
11986f7dacaSBenno Lossin //!                 }
12086f7dacaSBenno Lossin //!
12186f7dacaSBenno Lossin //!                 // All fields of `RawFoo` have been initialized, since `_p` is a ZST.
12286f7dacaSBenno Lossin //!                 Ok(())
12386f7dacaSBenno Lossin //!             })
12486f7dacaSBenno Lossin //!         }
12586f7dacaSBenno Lossin //!     }
12686f7dacaSBenno Lossin //! }
12786f7dacaSBenno Lossin //!
12886f7dacaSBenno Lossin //! #[pinned_drop]
12986f7dacaSBenno Lossin //! impl PinnedDrop for RawFoo {
13086f7dacaSBenno Lossin //!     fn drop(self: Pin<&mut Self>) {
13186f7dacaSBenno Lossin //!         // SAFETY: Since `foo` is initialized, destroying is safe.
13286f7dacaSBenno Lossin //!         unsafe { bindings::destroy_foo(self.foo.get()) };
13386f7dacaSBenno Lossin //!     }
13486f7dacaSBenno Lossin //! }
13586f7dacaSBenno Lossin //! ```
136578eb8b6SBenno Lossin 
137114ca41fSBenno Lossin use crate::{
138114ca41fSBenno Lossin     alloc::{AllocError, Flags},
139114ca41fSBenno Lossin     error::{self, Error},
140114ca41fSBenno Lossin };
141*dbd5058bSBenno Lossin use pin_init::{init_from_closure, pin_init_from_closure, Init, PinInit};
142114ca41fSBenno Lossin 
143114ca41fSBenno Lossin /// Smart pointer that can initialize memory in-place.
144114ca41fSBenno Lossin pub trait InPlaceInit<T>: Sized {
145114ca41fSBenno Lossin     /// Pinned version of `Self`.
146114ca41fSBenno Lossin     ///
147114ca41fSBenno Lossin     /// If a type already implicitly pins its pointee, `Pin<Self>` is unnecessary. In this case use
148114ca41fSBenno Lossin     /// `Self`, otherwise just use `Pin<Self>`.
149114ca41fSBenno Lossin     type PinnedSelf;
150114ca41fSBenno Lossin 
151114ca41fSBenno Lossin     /// Use the given pin-initializer to pin-initialize a `T` inside of a new smart pointer of this
152114ca41fSBenno Lossin     /// type.
153114ca41fSBenno Lossin     ///
154114ca41fSBenno Lossin     /// If `T: !Unpin` it will not be able to move afterwards.
try_pin_init<E>(init: impl PinInit<T, E>, flags: Flags) -> Result<Self::PinnedSelf, E> where E: From<AllocError>155114ca41fSBenno Lossin     fn try_pin_init<E>(init: impl PinInit<T, E>, flags: Flags) -> Result<Self::PinnedSelf, E>
156114ca41fSBenno Lossin     where
157114ca41fSBenno Lossin         E: From<AllocError>;
158114ca41fSBenno Lossin 
159114ca41fSBenno Lossin     /// Use the given pin-initializer to pin-initialize a `T` inside of a new smart pointer of this
160114ca41fSBenno Lossin     /// type.
161114ca41fSBenno Lossin     ///
162114ca41fSBenno Lossin     /// If `T: !Unpin` it will not be able to move afterwards.
pin_init<E>(init: impl PinInit<T, E>, flags: Flags) -> error::Result<Self::PinnedSelf> where Error: From<E>,163114ca41fSBenno Lossin     fn pin_init<E>(init: impl PinInit<T, E>, flags: Flags) -> error::Result<Self::PinnedSelf>
164114ca41fSBenno Lossin     where
165114ca41fSBenno Lossin         Error: From<E>,
166114ca41fSBenno Lossin     {
167114ca41fSBenno Lossin         // SAFETY: We delegate to `init` and only change the error type.
168114ca41fSBenno Lossin         let init = unsafe {
169114ca41fSBenno Lossin             pin_init_from_closure(|slot| init.__pinned_init(slot).map_err(|e| Error::from(e)))
170114ca41fSBenno Lossin         };
171114ca41fSBenno Lossin         Self::try_pin_init(init, flags)
172114ca41fSBenno Lossin     }
173114ca41fSBenno Lossin 
174114ca41fSBenno Lossin     /// Use the given initializer to in-place initialize a `T`.
try_init<E>(init: impl Init<T, E>, flags: Flags) -> Result<Self, E> where E: From<AllocError>175114ca41fSBenno Lossin     fn try_init<E>(init: impl Init<T, E>, flags: Flags) -> Result<Self, E>
176114ca41fSBenno Lossin     where
177114ca41fSBenno Lossin         E: From<AllocError>;
178114ca41fSBenno Lossin 
179114ca41fSBenno Lossin     /// Use the given initializer to in-place initialize a `T`.
init<E>(init: impl Init<T, E>, flags: Flags) -> error::Result<Self> where Error: From<E>,180114ca41fSBenno Lossin     fn init<E>(init: impl Init<T, E>, flags: Flags) -> error::Result<Self>
181114ca41fSBenno Lossin     where
182114ca41fSBenno Lossin         Error: From<E>,
183114ca41fSBenno Lossin     {
184114ca41fSBenno Lossin         // SAFETY: We delegate to `init` and only change the error type.
185114ca41fSBenno Lossin         let init = unsafe {
186114ca41fSBenno Lossin             init_from_closure(|slot| init.__pinned_init(slot).map_err(|e| Error::from(e)))
187114ca41fSBenno Lossin         };
188114ca41fSBenno Lossin         Self::try_init(init, flags)
189114ca41fSBenno Lossin     }
190114ca41fSBenno Lossin }
191114ca41fSBenno Lossin 
192578eb8b6SBenno Lossin /// Construct an in-place fallible initializer for `struct`s.
193578eb8b6SBenno Lossin ///
194578eb8b6SBenno Lossin /// This macro defaults the error to [`Error`]. If you need [`Infallible`], then use
195578eb8b6SBenno Lossin /// [`init!`].
196578eb8b6SBenno Lossin ///
197578eb8b6SBenno Lossin /// The syntax is identical to [`try_pin_init!`]. If you want to specify a custom error,
198578eb8b6SBenno Lossin /// append `? $type` after the `struct` initializer.
199578eb8b6SBenno Lossin /// The safety caveats from [`try_pin_init!`] also apply:
200578eb8b6SBenno Lossin /// - `unsafe` code must guarantee either full initialization or return an error and allow
201578eb8b6SBenno Lossin ///   deallocation of the memory.
202578eb8b6SBenno Lossin /// - the fields are initialized in the order given in the initializer.
203578eb8b6SBenno Lossin /// - no references to fields are allowed to be created inside of the initializer.
204578eb8b6SBenno Lossin ///
205578eb8b6SBenno Lossin /// # Examples
206578eb8b6SBenno Lossin ///
207578eb8b6SBenno Lossin /// ```rust
208*dbd5058bSBenno Lossin /// use kernel::error::Error;
209*dbd5058bSBenno Lossin /// use pin_init::zeroed;
210578eb8b6SBenno Lossin /// struct BigBuf {
211578eb8b6SBenno Lossin ///     big: KBox<[u8; 1024 * 1024 * 1024]>,
212578eb8b6SBenno Lossin ///     small: [u8; 1024 * 1024],
213578eb8b6SBenno Lossin /// }
214578eb8b6SBenno Lossin ///
215578eb8b6SBenno Lossin /// impl BigBuf {
216578eb8b6SBenno Lossin ///     fn new() -> impl Init<Self, Error> {
217578eb8b6SBenno Lossin ///         try_init!(Self {
218578eb8b6SBenno Lossin ///             big: KBox::init(zeroed(), GFP_KERNEL)?,
219578eb8b6SBenno Lossin ///             small: [0; 1024 * 1024],
220578eb8b6SBenno Lossin ///         }? Error)
221578eb8b6SBenno Lossin ///     }
222578eb8b6SBenno Lossin /// }
223578eb8b6SBenno Lossin /// ```
224578eb8b6SBenno Lossin ///
225578eb8b6SBenno Lossin /// [`Infallible`]: core::convert::Infallible
226*dbd5058bSBenno Lossin /// [`init!`]: pin_init::init
227578eb8b6SBenno Lossin /// [`try_pin_init!`]: crate::try_pin_init!
228578eb8b6SBenno Lossin /// [`Error`]: crate::error::Error
229578eb8b6SBenno Lossin #[macro_export]
230578eb8b6SBenno Lossin macro_rules! try_init {
231578eb8b6SBenno Lossin     ($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? {
232578eb8b6SBenno Lossin         $($fields:tt)*
233578eb8b6SBenno Lossin     }) => {
234*dbd5058bSBenno Lossin         ::pin_init::try_init!($(&$this in)? $t $(::<$($generics),* $(,)?>)? {
235578eb8b6SBenno Lossin             $($fields)*
236578eb8b6SBenno Lossin         }? $crate::error::Error)
237578eb8b6SBenno Lossin     };
238578eb8b6SBenno Lossin     ($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? {
239578eb8b6SBenno Lossin         $($fields:tt)*
240578eb8b6SBenno Lossin     }? $err:ty) => {
241*dbd5058bSBenno Lossin         ::pin_init::try_init!($(&$this in)? $t $(::<$($generics),* $(,)?>)? {
242578eb8b6SBenno Lossin             $($fields)*
243578eb8b6SBenno Lossin         }? $err)
244578eb8b6SBenno Lossin     };
245578eb8b6SBenno Lossin }
246578eb8b6SBenno Lossin 
247578eb8b6SBenno Lossin /// Construct an in-place, fallible pinned initializer for `struct`s.
248578eb8b6SBenno Lossin ///
249578eb8b6SBenno Lossin /// If the initialization can complete without error (or [`Infallible`]), then use [`pin_init!`].
250578eb8b6SBenno Lossin ///
251578eb8b6SBenno Lossin /// You can use the `?` operator or use `return Err(err)` inside the initializer to stop
252578eb8b6SBenno Lossin /// initialization and return the error.
253578eb8b6SBenno Lossin ///
254578eb8b6SBenno Lossin /// IMPORTANT: if you have `unsafe` code inside of the initializer you have to ensure that when
255578eb8b6SBenno Lossin /// initialization fails, the memory can be safely deallocated without any further modifications.
256578eb8b6SBenno Lossin ///
257578eb8b6SBenno Lossin /// This macro defaults the error to [`Error`].
258578eb8b6SBenno Lossin ///
259578eb8b6SBenno Lossin /// The syntax is identical to [`pin_init!`] with the following exception: you can append `? $type`
260578eb8b6SBenno Lossin /// after the `struct` initializer to specify the error type you want to use.
261578eb8b6SBenno Lossin ///
262578eb8b6SBenno Lossin /// # Examples
263578eb8b6SBenno Lossin ///
264578eb8b6SBenno Lossin /// ```rust
265578eb8b6SBenno Lossin /// # #![feature(new_uninit)]
266*dbd5058bSBenno Lossin /// use kernel::error::Error;
267*dbd5058bSBenno Lossin /// use pin_init::zeroed;
268578eb8b6SBenno Lossin /// #[pin_data]
269578eb8b6SBenno Lossin /// struct BigBuf {
270578eb8b6SBenno Lossin ///     big: KBox<[u8; 1024 * 1024 * 1024]>,
271578eb8b6SBenno Lossin ///     small: [u8; 1024 * 1024],
272578eb8b6SBenno Lossin ///     ptr: *mut u8,
273578eb8b6SBenno Lossin /// }
274578eb8b6SBenno Lossin ///
275578eb8b6SBenno Lossin /// impl BigBuf {
276578eb8b6SBenno Lossin ///     fn new() -> impl PinInit<Self, Error> {
277578eb8b6SBenno Lossin ///         try_pin_init!(Self {
278578eb8b6SBenno Lossin ///             big: KBox::init(zeroed(), GFP_KERNEL)?,
279578eb8b6SBenno Lossin ///             small: [0; 1024 * 1024],
280578eb8b6SBenno Lossin ///             ptr: core::ptr::null_mut(),
281578eb8b6SBenno Lossin ///         }? Error)
282578eb8b6SBenno Lossin ///     }
283578eb8b6SBenno Lossin /// }
284578eb8b6SBenno Lossin /// ```
285578eb8b6SBenno Lossin ///
286578eb8b6SBenno Lossin /// [`Infallible`]: core::convert::Infallible
287*dbd5058bSBenno Lossin /// [`pin_init!`]: pin_init::pin_init
288578eb8b6SBenno Lossin /// [`Error`]: crate::error::Error
289578eb8b6SBenno Lossin #[macro_export]
290578eb8b6SBenno Lossin macro_rules! try_pin_init {
291578eb8b6SBenno Lossin     ($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? {
292578eb8b6SBenno Lossin         $($fields:tt)*
293578eb8b6SBenno Lossin     }) => {
294*dbd5058bSBenno Lossin         ::pin_init::try_pin_init!($(&$this in)? $t $(::<$($generics),* $(,)?>)? {
295578eb8b6SBenno Lossin             $($fields)*
296578eb8b6SBenno Lossin         }? $crate::error::Error)
297578eb8b6SBenno Lossin     };
298578eb8b6SBenno Lossin     ($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? {
299578eb8b6SBenno Lossin         $($fields:tt)*
300578eb8b6SBenno Lossin     }? $err:ty) => {
301*dbd5058bSBenno Lossin         ::pin_init::try_pin_init!($(&$this in)? $t $(::<$($generics),* $(,)?>)? {
302578eb8b6SBenno Lossin             $($fields)*
303578eb8b6SBenno Lossin         }? $err)
304578eb8b6SBenno Lossin     };
305578eb8b6SBenno Lossin }
306