All of lore.kernel.org
 help / color / mirror / Atom feed
From: Andreas Hindborg <nmi@metaspace.dk>
To: Benno Lossin <y86-dev@protonmail.com>
Cc: "Miguel Ojeda" <ojeda@kernel.org>,
	"Alex Gaynor" <alex.gaynor@gmail.com>,
	"Wedson Almeida Filho" <wedsonaf@gmail.com>,
	"Boqun Feng" <boqun.feng@gmail.com>,
	"Gary Guo" <gary@garyguo.net>,
	"Björn Roy Baron" <bjorn3_gh@protonmail.com>,
	"Alice Ryhl" <alice@ryhl.io>,
	rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org,
	patches@lists.linux.dev, "Alice Ryhl" <aliceryhl@google.com>,
	"Andreas Hindborg" <a.hindborg@samsung.com>
Subject: Re: [PATCH v6 11/15] rust: init: add `Zeroable` trait and `init::zeroed` function
Date: Thu, 06 Apr 2023 00:08:28 +0200	[thread overview]
Message-ID: <87lej6rngc.fsf@metaspace.dk> (raw)
In-Reply-To: <20230405193445.745024-12-y86-dev@protonmail.com>


Benno Lossin <y86-dev@protonmail.com> writes:

> Add the `Zeroable` trait which marks types that can be initialized by
> writing `0x00` to every byte of the type. Also add the `init::zeroed`
> function that creates an initializer for a `Zeroable` type that writes
> `0x00` to every byte.
>
> Signed-off-by: Benno Lossin <y86-dev@protonmail.com>
> Reviewed-by: Alice Ryhl <aliceryhl@google.com>
> Reviewed-by: Gary Guo <gary@garyguo.net>
> Cc: Andreas Hindborg <a.hindborg@samsung.com>
> ---

Reviewed-by: Andreas Hindborg <a.hindborg@samsung.com>

>  rust/kernel/init.rs | 97 ++++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 95 insertions(+), 2 deletions(-)
>
> diff --git a/rust/kernel/init.rs b/rust/kernel/init.rs
> index 99751375e7c8..ffd539e2f5ef 100644
> --- a/rust/kernel/init.rs
> +++ b/rust/kernel/init.rs
> @@ -195,8 +195,14 @@ use crate::{
>  };
>  use alloc::boxed::Box;
>  use core::{
> -    alloc::AllocError, cell::Cell, convert::Infallible, marker::PhantomData, mem::MaybeUninit,
> -    pin::Pin, ptr,
> +    alloc::AllocError,
> +    cell::Cell,
> +    convert::Infallible,
> +    marker::PhantomData,
> +    mem::MaybeUninit,
> +    num::*,
> +    pin::Pin,
> +    ptr::{self, NonNull},
>  };
>
>  #[doc(hidden)]
> @@ -1323,3 +1329,90 @@ pub unsafe trait PinnedDrop: __internal::HasPinData {
>      /// automatically.
>      fn drop(self: Pin<&mut Self>, only_call_from_drop: __internal::OnlyCallFromDrop);
>  }
> +
> +/// Marker trait for types that can be initialized by writing just zeroes.
> +///
> +/// # Safety
> +///
> +/// The bit pattern consisting of only zeroes is a valid bit pattern for this type. In other words,
> +/// this is not UB:
> +///
> +/// ```rust,ignore
> +/// let val: Self = unsafe { core::mem::zeroed() };
> +/// ```
> +pub unsafe trait Zeroable {}
> +
> +/// Create a new zeroed T.
> +///
> +/// The returned initializer will write `0x00` to every byte of the given `slot`.
> +#[inline]
> +pub fn zeroed<T: Zeroable>() -> impl Init<T> {
> +    // SAFETY: Because `T: Zeroable`, all bytes zero is a valid bit pattern for `T`
> +    // and because we write all zeroes, the memory is initialized.
> +    unsafe {
> +        init_from_closure(|slot: *mut T| {
> +            slot.write_bytes(0, 1);
> +            Ok(())
> +        })
> +    }
> +}
> +
> +macro_rules! impl_zeroable {
> +    ($($({$($generics:tt)*})? $t:ty, )*) => {
> +        $(unsafe impl$($($generics)*)? Zeroable for $t {})*
> +    };
> +}
> +
> +impl_zeroable! {
> +    // SAFETY: All primitives that are allowed to be zero.
> +    bool,
> +    char,
> +    u8, u16, u32, u64, u128, usize,
> +    i8, i16, i32, i64, i128, isize,
> +    f32, f64,
> +
> +    // SAFETY: These are ZSTs, there is nothing to zero.
> +    {<T: ?Sized>} PhantomData<T>, core::marker::PhantomPinned, Infallible, (),
> +
> +    // SAFETY: Type is allowed to take any value, including all zeros.
> +    {<T>} MaybeUninit<T>,
> +
> +    // SAFETY: All zeros is equivalent to `None` (option layout optimization guarantee).
> +    Option<NonZeroU8>, Option<NonZeroU16>, Option<NonZeroU32>, Option<NonZeroU64>,
> +    Option<NonZeroU128>, Option<NonZeroUsize>,
> +    Option<NonZeroI8>, Option<NonZeroI16>, Option<NonZeroI32>, Option<NonZeroI64>,
> +    Option<NonZeroI128>, Option<NonZeroIsize>,
> +
> +    // SAFETY: All zeros is equivalent to `None` (option layout optimization guarantee).
> +    //
> +    // In this case we are allowed to use `T: ?Sized`, since all zeros is the `None` variant.
> +    {<T: ?Sized>} Option<NonNull<T>>,
> +    {<T: ?Sized>} Option<Box<T>>,
> +
> +    // SAFETY: `null` pointer is valid.
> +    //
> +    // We cannot use `T: ?Sized`, since the VTABLE pointer part of fat pointers is not allowed to be
> +    // null.
> +    //
> +    // When `Pointee` gets stabilized, we could use
> +    // `T: ?Sized where <T as Pointee>::Metadata: Zeroable`
> +    {<T>} *mut T, {<T>} *const T,
> +
> +    // SAFETY: `null` pointer is valid and the metadata part of these fat pointers is allowed to be
> +    // zero.
> +    {<T>} *mut [T], {<T>} *const [T], *mut str, *const str,
> +
> +    // SAFETY: `T` is `Zeroable`.
> +    {<const N: usize, T: Zeroable>} [T; N], {<T: Zeroable>} Wrapping<T>,
> +}
> +
> +macro_rules! impl_tuple_zeroable {
> +    ($(,)?) => {};
> +    ($first:ident, $($t:ident),* $(,)?) => {
> +        // SAFETY: All elements are zeroable and padding can be zero.
> +        unsafe impl<$first: Zeroable, $($t: Zeroable),*> Zeroable for ($first, $($t),*) {}
> +        impl_tuple_zeroable!($($t),* ,);
> +    }
> +}
> +
> +impl_tuple_zeroable!(A, B, C, D, E, F, G, H, I, J);


  reply	other threads:[~2023-04-05 22:09 UTC|newest]

Thread overview: 30+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-04-05 19:35 [PATCH v6 00/15] Rust pin-init API for pinned initialization of structs Benno Lossin
2023-04-05 19:35 ` [PATCH v6 01/15] rust: enable the `pin_macro` feature Benno Lossin
2023-04-05 20:45   ` Andreas Hindborg
2023-04-05 19:35 ` [PATCH v6 02/15] rust: macros: add `quote!` macro Benno Lossin
2023-04-05 19:35 ` [PATCH v6 03/15] rust: sync: change error type of constructor functions Benno Lossin
2023-04-05 19:35 ` [PATCH v6 04/15] rust: sync: add `assume_init` to `UniqueArc` Benno Lossin
2023-04-05 19:35 ` [PATCH v6 05/15] rust: types: add `Opaque::raw_get` Benno Lossin
2023-04-05 19:36 ` [PATCH v6 06/15] rust: add pin-init API core Benno Lossin
2023-04-05 21:04   ` Andreas Hindborg
2023-04-05 19:36 ` [PATCH v6 07/15] rust: init: add initialization macros Benno Lossin
2023-04-05 21:14   ` Andreas Hindborg
2023-04-05 19:36 ` [PATCH v6 08/15] rust: init/sync: add `InPlaceInit` trait to pin-initialize smart pointers Benno Lossin
2023-04-05 21:34   ` Andreas Hindborg
2023-04-05 19:36 ` [PATCH v6 09/15] rust: init: add `PinnedDrop` trait and macros Benno Lossin
2023-04-05 21:40   ` Andreas Hindborg
2023-04-05 19:36 ` [PATCH v6 10/15] rust: init: add `stack_pin_init!` macro Benno Lossin
2023-04-05 19:59   ` Gary Guo
2023-04-05 21:51   ` Andreas Hindborg
2023-04-05 19:36 ` [PATCH v6 11/15] rust: init: add `Zeroable` trait and `init::zeroed` function Benno Lossin
2023-04-05 22:08   ` Andreas Hindborg [this message]
2023-04-05 19:36 ` [PATCH v6 12/15] rust: prelude: add `pin-init` API items to prelude Benno Lossin
2023-04-05 19:36 ` [PATCH v6 13/15] rust: types: add common init-helper functions for `Opaque` Benno Lossin
2023-04-05 20:18   ` Gary Guo
2023-04-06  6:56   ` [PATCH v6.1] rust: types: add `Opaque::pin_init` Benno Lossin
2023-04-05 19:36 ` [PATCH v6 14/15] rust: sync: reduce stack usage of `UniqueArc::try_new_uninit` Benno Lossin
2023-04-05 21:59   ` Andreas Hindborg
2023-04-05 19:36 ` [PATCH v6 15/15] rust: sync: add functions for initializing `UniqueArc<MaybeUninit<T>>` Benno Lossin
2023-04-05 21:02 ` [PATCH v6 00/15] Rust pin-init API for pinned initialization of structs Boqun Feng
2023-04-05 21:06   ` Benno Lossin
2023-04-05 21:11     ` Boqun Feng

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=87lej6rngc.fsf@metaspace.dk \
    --to=nmi@metaspace.dk \
    --cc=a.hindborg@samsung.com \
    --cc=alex.gaynor@gmail.com \
    --cc=alice@ryhl.io \
    --cc=aliceryhl@google.com \
    --cc=bjorn3_gh@protonmail.com \
    --cc=boqun.feng@gmail.com \
    --cc=gary@garyguo.net \
    --cc=linux-kernel@vger.kernel.org \
    --cc=ojeda@kernel.org \
    --cc=patches@lists.linux.dev \
    --cc=rust-for-linux@vger.kernel.org \
    --cc=wedsonaf@gmail.com \
    --cc=y86-dev@protonmail.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 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.