All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Alexandre Courbot" <acourbot@nvidia.com>
To: "Boqun Feng" <boqun.feng@gmail.com>
Cc: "Miguel Ojeda" <ojeda@kernel.org>,
	"Alex Gaynor" <alex.gaynor@gmail.com>,
	"Gary Guo" <gary@garyguo.net>,
	"Björn Roy Baron" <bjorn3_gh@protonmail.com>,
	"Andreas Hindborg" <a.hindborg@kernel.org>,
	"Alice Ryhl" <aliceryhl@google.com>,
	"Trevor Gross" <tmgross@umich.edu>,
	"Danilo Krummrich" <dakr@kernel.org>,
	"David Airlie" <airlied@gmail.com>,
	"Simona Vetter" <simona@ffwll.ch>,
	"Maarten Lankhorst" <maarten.lankhorst@linux.intel.com>,
	"Maxime Ripard" <mripard@kernel.org>,
	"Thomas Zimmermann" <tzimmermann@suse.de>,
	"Benno Lossin" <lossin@kernel.org>,
	"John Hubbard" <jhubbard@nvidia.com>,
	"Ben Skeggs" <bskeggs@nvidia.com>,
	"Joel Fernandes" <joelagnelf@nvidia.com>,
	"Timur Tabi" <ttabi@nvidia.com>,
	"Alistair Popple" <apopple@nvidia.com>,
	linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org,
	nouveau@lists.freedesktop.org, dri-devel@lists.freedesktop.org
Subject: Re: [PATCH v5 04/23] rust: add new `num` module with `PowerOfTwo` type
Date: Fri, 13 Jun 2025 23:16:10 +0900	[thread overview]
Message-ID: <DALGWEM3TD3O.95L77CD6R62S@nvidia.com> (raw)
In-Reply-To: <aErtL6yxLu3Azbsm@tardis.local>

On Fri Jun 13, 2025 at 12:07 AM JST, Boqun Feng wrote:
> On Thu, Jun 12, 2025 at 11:01:32PM +0900, Alexandre Courbot wrote:
>> Introduce the `num` module, featuring the `PowerOfTwo` unsigned wrapper
>> that guarantees (at build-time or runtime) that a value is a power of
>> two.
>> 
>> Such a property is often useful to maintain. In the context of the
>> kernel, powers of two are often used to align addresses or sizes up and
>> down, or to create masks. These operations are provided by this type.
>> 
>> It is introduced to be first used by the nova-core driver.
>> 
>> Signed-off-by: Alexandre Courbot <acourbot@nvidia.com>
>> ---
>>  rust/kernel/lib.rs |   1 +
>>  rust/kernel/num.rs | 173 +++++++++++++++++++++++++++++++++++++++++++++++++++++
>>  2 files changed, 174 insertions(+)
>> 
>> diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs
>> index 6b4774b2b1c37f4da1866e993be6230bc6715841..2955f65da1278dd4cba1e4272ff178b8211a892c 100644
>> --- a/rust/kernel/lib.rs
>> +++ b/rust/kernel/lib.rs
>> @@ -89,6 +89,7 @@
>>  pub mod mm;
>>  #[cfg(CONFIG_NET)]
>>  pub mod net;
>> +pub mod num;
>>  pub mod of;
>>  #[cfg(CONFIG_PM_OPP)]
>>  pub mod opp;
>> diff --git a/rust/kernel/num.rs b/rust/kernel/num.rs
>> new file mode 100644
>> index 0000000000000000000000000000000000000000..ee0f67ad1a89e69f5f8d2077eba5541b472e7d8a
>> --- /dev/null
>> +++ b/rust/kernel/num.rs
>> @@ -0,0 +1,173 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +
>> +//! Numerical and binary utilities for primitive types.
>> +
>> +use crate::build_assert;
>> +use core::borrow::Borrow;
>> +use core::fmt::Debug;
>> +use core::hash::Hash;
>> +use core::ops::Deref;
>> +
>> +/// An unsigned integer which is guaranteed to be a power of 2.
>> +#[derive(Debug, Clone, Copy)]
>> +#[repr(transparent)]
>> +pub struct PowerOfTwo<T>(T);
>> +
>> +macro_rules! power_of_two_impl {
>> +    ($($t:ty),+) => {
>> +        $(
>> +            impl PowerOfTwo<$t> {
>> +                /// Validates that `v` is a power of two at build-time, and returns it wrapped into
>> +                /// `PowerOfTwo`.
>> +                ///
>> +                /// A build error is triggered if `v` cannot be asserted to be a power of two.
>> +                ///
>> +                /// # Examples
>> +                ///
>> +                /// ```
>> +                /// use kernel::num::PowerOfTwo;
>> +                ///
>> +                /// let v = PowerOfTwo::<u32>::new(256);
>> +                /// assert_eq!(v.value(), 256);
>> +                /// ```
>> +                #[inline(always)]
>> +                pub const fn new(v: $t) -> Self {
>
> Then this function should be unsafe, because an invalid `v` can create
> an invalid PowerOfTwo.

Doesn't the `build_assert` below allow us to keep this method safe,
since it will fail at build-time if it cannot be asserted that `v` is a
power of two?

>
>> +                    build_assert!(v.count_ones() == 1);
>> +                    Self(v)
>> +                }
>> +
>> +                /// Validates that `v` is a power of two at runtime, and returns it wrapped into
>> +                /// `PowerOfTwo`.
>> +                ///
>> +                /// `None` is returned if `v` was not a power of two.
>> +                ///
>> +                /// # Examples
>> +                ///
>> +                /// ```
>> +                /// use kernel::num::PowerOfTwo;
>> +                ///
>> +                /// assert_eq!(PowerOfTwo::<u32>::try_new(16).unwrap().value(), 16);
>> +                /// assert_eq!(PowerOfTwo::<u32>::try_new(15), None);
>> +                /// ```
>> +                #[inline(always)]
>> +                pub const fn try_new(v: $t) -> Option<Self> {
>> +                    match v.count_ones() {
>> +                        1 => Some(Self(v)),
>> +                        _ => None,
>> +                    }
>> +                }
>> +
>> +                /// Returns the value of this instance.
>> +                ///
>> +                /// It is guaranteed to be a power of two.
>> +                ///
>> +                /// # Examples
>> +                ///
>> +                /// ```
>> +                /// use kernel::num::PowerOfTwo;
>> +                ///
>> +                /// let v = PowerOfTwo::<u32>::new(256);
>> +                /// assert_eq!(v.value(), 256);
>> +                /// ```
>> +                #[inline(always)]
>> +                pub const fn value(&self) -> $t {
>> +                    self.0
>> +                }
>> +
>> +                /// Returns the mask corresponding to `self.value() - 1`.
>> +                #[inline(always)]
>> +                pub const fn mask(&self) -> $t {
>> +                    self.0.wrapping_sub(1)
>> +                }
>> +
>> +                /// Aligns `self` down to `alignment`.
>> +                ///
>> +                /// # Examples
>> +                ///
>> +                /// ```
>> +                /// use kernel::num::PowerOfTwo;
>> +                ///
>> +                /// assert_eq!(PowerOfTwo::<u32>::new(0x1000).align_down(0x4fff), 0x4000);
>> +                /// ```
>> +                #[inline(always)]
>> +                pub const fn align_down(self, value: $t) -> $t {
>
> I'm late to party, but could we instead implement:
>
>     pub const fn round_down<i32>(value: i32, shift: i32) -> i32 {
>         value & !((1 << shift) - 1)
>     }
>
>     pub const fn round_up<i32>(value: i32, shift: i32) -> i32 {
>         let mask = (1 << shift) - 1;
>         value.wrapping_add(mask) & !mask
>     }
>
> ? It's much harder to pass an invalid alignment with this.

It also forces you to think in terms of shifts instead of values - i.e.
you cannot round to `0x1000` as it commonly done in the kernel, now you
need to do some mental gymnastics to know it is actually a shift of `12`.
Being able to use the actual value to round to is more familiar (and
natural) to me.

  parent reply	other threads:[~2025-06-13 14:16 UTC|newest]

Thread overview: 58+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-06-12 14:01 [PATCH v5 00/23] nova-core: run FWSEC-FRTS to perform first stage of GSP initialization Alexandre Courbot
2025-06-12 14:01 ` [PATCH v5 01/23] rust: dma: expose the count and size of CoherentAllocation Alexandre Courbot
2025-06-12 14:01 ` [PATCH v5 02/23] rust: make ETIMEDOUT error available Alexandre Courbot
2025-06-12 14:01 ` [PATCH v5 03/23] rust: sizes: add constants up to SZ_2G Alexandre Courbot
2025-06-12 14:01 ` [PATCH v5 04/23] rust: add new `num` module with `PowerOfTwo` type Alexandre Courbot
2025-06-12 15:07   ` Boqun Feng
2025-06-12 20:00     ` John Hubbard
2025-06-12 20:05       ` Boqun Feng
2025-06-12 20:08         ` John Hubbard
2025-06-12 20:12           ` Boqun Feng
2025-06-13 14:16     ` Alexandre Courbot [this message]
2025-06-13 15:25       ` Boqun Feng
2025-06-14 17:08       ` Boqun Feng
2025-06-16  5:14         ` Alexandre Courbot
2025-06-14 17:31   ` Boqun Feng
2025-06-16  5:19     ` Alexandre Courbot
2025-06-14 19:09   ` Benno Lossin
2025-06-15 13:32   ` Miguel Ojeda
2025-06-16  5:13     ` Alexandre Courbot
2025-06-12 14:01 ` [PATCH v5 05/23] rust: num: add the `fls` operation Alexandre Courbot
2025-06-14 19:16   ` Benno Lossin
2025-06-16  6:41     ` Alexandre Courbot
2025-06-18 19:24       ` Benno Lossin
2025-06-19 13:26         ` Alexandre Courbot
2025-06-19 13:28           ` Benno Lossin
2025-06-15  9:37   ` Miguel Ojeda
2025-06-15 10:51     ` Alexandre Courbot
2025-06-15 10:58       ` Alexandre Courbot
2025-06-15 13:25         ` Miguel Ojeda
2025-06-16  6:36           ` Alexandre Courbot
2025-06-12 14:01 ` [PATCH v5 06/23] gpu: nova-core: use absolute paths in register!() macro Alexandre Courbot
2025-06-12 14:01 ` [PATCH v5 07/23] gpu: nova-core: add delimiter for helper rules " Alexandre Courbot
2025-06-12 14:01 ` [PATCH v5 08/23] gpu: nova-core: expose the offset of each register as a type constant Alexandre Courbot
2025-06-12 14:01 ` [PATCH v5 09/23] gpu: nova-core: allow register aliases Alexandre Courbot
2025-06-12 14:01 ` [PATCH v5 10/23] gpu: nova-core: increase BAR0 size to 16MB Alexandre Courbot
2025-06-12 14:01 ` [PATCH v5 11/23] gpu: nova-core: add helper function to wait on condition Alexandre Courbot
2025-06-12 14:01 ` [PATCH v5 12/23] gpu: nova-core: wait for GFW_BOOT completion Alexandre Courbot
2025-06-12 14:01 ` [PATCH v5 13/23] gpu: nova-core: add DMA object struct Alexandre Courbot
2025-06-12 14:01 ` [PATCH v5 14/23] gpu: nova-core: register sysmem flush page Alexandre Courbot
2025-06-12 14:01 ` [PATCH v5 15/23] gpu: nova-core: add falcon register definitions and base code Alexandre Courbot
2025-06-17 16:33   ` Danilo Krummrich
2025-06-18  5:26     ` Alexandre Courbot
2025-06-12 14:01 ` [PATCH v5 16/23] gpu: nova-core: firmware: add ucode descriptor used by FWSEC-FRTS Alexandre Courbot
2025-06-12 14:01 ` [PATCH v5 17/23] gpu: nova-core: vbios: Add base support for VBIOS construction and iteration Alexandre Courbot
2025-06-12 14:01 ` [PATCH v5 18/23] gpu: nova-core: vbios: Add support to look up PMU table in FWSEC Alexandre Courbot
2025-06-12 14:01 ` [PATCH v5 19/23] gpu: nova-core: vbios: Add support for FWSEC ucode extraction Alexandre Courbot
2025-06-12 14:01 ` [PATCH v5 20/23] gpu: nova-core: compute layout of the FRTS region Alexandre Courbot
2025-06-12 14:01 ` [PATCH v5 21/23] gpu: nova-core: add types for patching firmware binaries Alexandre Courbot
2025-06-12 14:01 ` [PATCH v5 22/23] gpu: nova-core: extract FWSEC from BIOS and patch it to run FWSEC-FRTS Alexandre Courbot
2025-06-12 14:01 ` [PATCH v5 23/23] gpu: nova-core: load and " Alexandre Courbot
2025-06-18 20:23   ` Danilo Krummrich
2025-06-18 20:24     ` Danilo Krummrich
2025-06-19 12:35       ` Alexandre Courbot
2025-06-19 12:43         ` Danilo Krummrich
2025-06-17 20:14 ` [PATCH v5 00/23] nova-core: run FWSEC-FRTS to perform first stage of GSP initialization Danilo Krummrich
2025-06-18  8:25   ` Alexandre Courbot
2025-06-18 20:14 ` Danilo Krummrich
2025-06-19  7:14   ` Alexandre Courbot

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=DALGWEM3TD3O.95L77CD6R62S@nvidia.com \
    --to=acourbot@nvidia.com \
    --cc=a.hindborg@kernel.org \
    --cc=airlied@gmail.com \
    --cc=alex.gaynor@gmail.com \
    --cc=aliceryhl@google.com \
    --cc=apopple@nvidia.com \
    --cc=bjorn3_gh@protonmail.com \
    --cc=boqun.feng@gmail.com \
    --cc=bskeggs@nvidia.com \
    --cc=dakr@kernel.org \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=gary@garyguo.net \
    --cc=jhubbard@nvidia.com \
    --cc=joelagnelf@nvidia.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=lossin@kernel.org \
    --cc=maarten.lankhorst@linux.intel.com \
    --cc=mripard@kernel.org \
    --cc=nouveau@lists.freedesktop.org \
    --cc=ojeda@kernel.org \
    --cc=rust-for-linux@vger.kernel.org \
    --cc=simona@ffwll.ch \
    --cc=tmgross@umich.edu \
    --cc=ttabi@nvidia.com \
    --cc=tzimmermann@suse.de \
    /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.