From: Yury Norov <yury.norov@gmail.com>
To: Alexandre Courbot <acourbot@nvidia.com>
Cc: "Danilo Krummrich" <dakr@kernel.org>,
"Joel Fernandes" <joelagnelf@nvidia.com>,
"Jesung Yang" <y.j3ms.n@gmail.com>,
"Miguel Ojeda" <ojeda@kernel.org>,
"Alex Gaynor" <alex.gaynor@gmail.com>,
"Boqun Feng" <boqun.feong@gmail.com>,
"Gary Guo" <gary@garyguo.net>,
"Björn Roy Baron" <bjorn3_gh@protonmail.com>,
"Benno Lossin" <lossin@kernel.org>,
"Andreas Hindborg" <a.hindborg@kernel.org>,
"Alice Ryhl" <aliceryhl@google.com>,
"Trevor Gross" <tmgross@umich.edu>,
nouveau@lists.freedesktop.org, linux-kernel@vger.kernel.org,
rust-for-linux@vger.kernel.org
Subject: Re: [PATCH RFC v2 3/3] gpu: nova-core: use BoundedInt
Date: Thu, 9 Oct 2025 12:40:58 -0400 [thread overview]
Message-ID: <aOflmmHe8O6Nx9Hp@yury> (raw)
In-Reply-To: <20251009-bounded_ints-v2-3-ff3d7fee3ffd@nvidia.com>
Hi Alexandre,
On Thu, Oct 09, 2025 at 09:37:10PM +0900, Alexandre Courbot wrote:
> Use BoundedInt with the register!() macro and adapt the nova-core code
> accordingly. This makes it impossible to trim values when setting a
> register field, because either the value of the field has been inferred
> at compile-time to fit within the bounds of the field, or the user has
> been forced to check at runtime that it does indeed fit.
In C23 we've got _BitInt(), which works like:
unsigned _BitInt(2) a = 5; // compile-time error
Can you consider a similar name and syntax in rust?
> The use of BoundedInt actually simplifies register fields definitions,
> as they don't need an intermediate storage type (the "as ..." part of
> fields definitions). Instead, the internal storage type for each field
> is now the bounded integer of its width in bits, which can optionally be
> converted to another type that implements `From`` or `TryFrom`` for that
> bounded integer type.
>
> This means that something like
>
> register!(NV_PDISP_VGA_WORKSPACE_BASE @ 0x00625f04 {
> 3:3 status_valid as bool,
> 31:8 addr as u32,
> });
>
> Now becomes
>
> register!(NV_PDISP_VGA_WORKSPACE_BASE @ 0x00625f04 {
> 3:3 status_valid => bool,
> 31:8 addr,
> });
That looks nicer, really. But now that you don't make user to provide
a representation type, how would one distinguish signed and unsigned
fields? Assuming that BoundedInt is intended to become a generic type,
people may want to use it as a storage for counters and other
non-bitfield type of things. Maybe:
register!(NV_PDISP_VGA_WORKSPACE_BASE @ 0x00625f04 {
s 3:0 cnt,
7:4 flags, // implies unsigned - ?
u 31:8 addr,
});
> (here `status_valid` is infallibly converted to a bool for convenience
> and to remain compatible with the previous semantics)
>
> The field setter/getters are also simplified. If a field has no target
> type, then its setter expects any type that implements `Into` to the
> field's bounded integer type. Due to the many `From` implementations for
> primitive types, this means that most calls can be left unchanged. If
> the caller passes a value that is potentially larger than the field's
> capacity, it must use the `try_` variant of the setter, which returns an
> error if the value cannot be converted at runtime.
>
> For fields that use `=>` to convert to another type, both setter and
> getter are always infallible.
>
> For fields that use `?=>` to fallibly convert to another type, only the
> getter needs to be fallible as the setter always provide valid values by
> design.
Can you share a couple examples? Not sure I understand this part,
especially how setters may not be fallible, and getters may fail.
> Outside of the register macro, the biggest changes occur in `falcon.rs`,
> which defines many enums for fields - their conversion implementations
> need to be changed from the original primitive type of the field to the
> new corresponding bounded int type. Hopefully the TryFrom/Into derive
> macros [1] can take care of implementing these, but it will need to be
> adapted to support bounded integers... :/
>
> But overall, I am rather happy at how simple it was to convert the whole
> of nova-core to this.
>
> Note: This RFC uses nova-core's register!() macro for practical
> purposes, but the hope is to move this patch on top of the bitfield
> macro after it is split out [2].
>
> [1] https://lore.kernel.org/rust-for-linux/cover.1755235180.git.y.j3ms.n@gmail.com/
> [2] https://lore.kernel.org/rust-for-linux/20251003154748.1687160-1-joelagnelf@nvidia.com/
>
> Signed-off-by: Alexandre Courbot <acourbot@nvidia.com>
> ---
...
> regs::NV_PFALCON_FALCON_DMATRFBASE1::default()
> - .set_base((dma_start >> 40) as u16)
> + .try_set_base(dma_start >> 40)?
> .write(bar, &E::ID);
Does it mean that something like the following syntax is possible?
regs::NV_PFALCON_FALCON_DMATRFBASE1::default()
.try_set_base1(base1 >> 40)? // fail here
.try_set_base2(base2 >> 40)? // skip
.write(bar, &E::ID) else { pr_err!(); return -EINVAL };
This is my main concern: Rust is advertised a as runtime-safe language
(at lease safer than C), but current design isn't safe against one of
the most common errors: type overflow.
If your syntax above allows to handle errors in .try_set() path this way
or another, I think the rest is manageable.
As a side note: it's a huge pain in C to grep for functions that
defined by using a macro. Here you do a similar thing. One can't
easily grep the 'try_set_base' implementation, and would have to
make a not so pleasant detour to the low-level internals. Maybe
switch it to:
regs::NV_PFALCON_FALCON_DMATRFBASE1::default()
.try_set(base, dma_start >> 40)?
.write(bar, &E::ID);
Thanks,
Yury
next prev parent reply other threads:[~2025-12-13 12:45 UTC|newest]
Thread overview: 26+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-10-09 12:37 [RFC PATCH v2 0/3] rust: bounded integer types and use in register macro Alexandre Courbot
2025-10-09 12:37 ` [PATCH RFC v2 1/3] gpu: nova-core: register: use field type for Into implementation Alexandre Courbot
2025-10-09 15:17 ` Joel Fernandes
2025-10-09 15:41 ` Joel Fernandes
2025-10-10 8:24 ` Alexandre Courbot
2025-10-10 8:26 ` Alexandre Courbot
2025-10-10 14:59 ` Joel Fernandes
2025-10-09 20:10 ` Edwin Peer
2025-10-16 14:51 ` Joel Fernandes
2025-10-09 12:37 ` [PATCH RFC v2 2/3] rust: kernel: add bounded integer types Alexandre Courbot
2025-10-09 21:33 ` Joel Fernandes
2025-10-10 8:49 ` Alexandre Courbot
2025-10-10 15:23 ` Joel Fernandes
2025-10-11 10:33 ` Alice Ryhl
2025-10-09 12:37 ` [PATCH RFC v2 3/3] gpu: nova-core: use BoundedInt Alexandre Courbot
2025-10-09 16:40 ` Yury Norov [this message]
2025-10-09 17:18 ` Danilo Krummrich
2025-10-09 18:28 ` Yury Norov
2025-10-09 18:37 ` Joel Fernandes
2025-10-09 19:19 ` Miguel Ojeda
2025-10-09 19:34 ` Danilo Krummrich
2025-10-09 18:29 ` Joel Fernandes
2025-10-10 9:19 ` Alexandre Courbot
2025-10-10 17:20 ` Yury Norov
2025-10-10 17:58 ` Danilo Krummrich
2025-10-13 13:58 ` Joel Fernandes
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=aOflmmHe8O6Nx9Hp@yury \
--to=yury.norov@gmail.com \
--cc=a.hindborg@kernel.org \
--cc=acourbot@nvidia.com \
--cc=alex.gaynor@gmail.com \
--cc=aliceryhl@google.com \
--cc=bjorn3_gh@protonmail.com \
--cc=boqun.feong@gmail.com \
--cc=dakr@kernel.org \
--cc=gary@garyguo.net \
--cc=joelagnelf@nvidia.com \
--cc=linux-kernel@vger.kernel.org \
--cc=lossin@kernel.org \
--cc=nouveau@lists.freedesktop.org \
--cc=ojeda@kernel.org \
--cc=rust-for-linux@vger.kernel.org \
--cc=tmgross@umich.edu \
--cc=y.j3ms.n@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 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.