From: "Alexandre Courbot" <acourbot@nvidia.com>
To: "Danilo Krummrich" <dakr@kernel.org>
Cc: "Miguel Ojeda" <ojeda@kernel.org>,
"Alex Gaynor" <alex.gaynor@gmail.com>,
"Boqun Feng" <boqun.feng@gmail.com>,
"Gary Guo" <gary@garyguo.net>,
"Björn Roy Baron" <bjorn3_gh@protonmail.com>,
"Benno Lossin" <benno.lossin@proton.me>,
"Andreas Hindborg" <a.hindborg@kernel.org>,
"Alice Ryhl" <aliceryhl@google.com>,
"Trevor Gross" <tmgross@umich.edu>,
"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>,
"Jonathan Corbet" <corbet@lwn.net>,
"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 06/16] gpu: nova-core: define registers layout using helper macro
Date: Mon, 28 Apr 2025 23:27:26 +0900 [thread overview]
Message-ID: <D9ICBZ1DGGVU.2AKUD3X883TMB@nvidia.com> (raw)
In-Reply-To: <aAdvdczmQYBAS7vs@cassiopeiae>
Hi Danilo,
On Tue Apr 22, 2025 at 7:29 PM JST, Danilo Krummrich wrote:
> On Sun, Apr 20, 2025 at 09:19:38PM +0900, Alexandre Courbot wrote:
>> Add the register!() macro, which defines a given register's layout and
>> provide bit-field accessors with a way to convert them to a given type.
>> This macro will allow us to make clear definitions of the registers and
>> manipulate their fields safely.
>>
>> The long-term goal is to eventually move it to the kernel crate so it
>> can be used my other drivers as well, but it was agreed to first land it
>> into nova-core and make it mature there.
>>
>> To illustrate its usage, use it to define the layout for the Boot0
>> register and use its accessors through the use of the convenience
>> with_bar!() macro, which uses Revocable::try_access() and converts its
>
> s/try_access/try_access_with/
Fixed, thanks.
>
>> returned Option into the proper error as needed.
>
> Using try_access_with() / with_bar! should be a separate patch.
Agreed - done.
>> +register!(Boot0@0x00000000, "Basic revision information about the GPU";
>> + 3:0 minor_rev => as u8, "minor revision of the chip";
>> + 7:4 major_rev => as u8, "major revision of the chip";
>> + 28:20 chipset => try_into Chipset, "chipset model"
>
> Should we preserve the information that this is the combination of two register
> fields?
I've tried to reproduce what the current code did, but indeed according
to OpenRM these are two different fields, `architecture` and
`implementation`.
There's also more: `architecture` is a split field, with its MSB at a
different index from the rest. Right now the MSB is always 0 but the
lower bits are dangerously close to overflowing.
Thankfully, the macro doesn't prevent from extending its definition with
an extra impl block, so I've done just that to provide the correct
architecture as well as the `chipset` pseudo-field that will be the one
we use in the code anyway.
>
>> +);
>> diff --git a/drivers/gpu/nova-core/regs/macros.rs b/drivers/gpu/nova-core/regs/macros.rs
>> new file mode 100644
>> index 0000000000000000000000000000000000000000..fa9bd6b932048113de997658b112885666e694c9
>> --- /dev/null
>> +++ b/drivers/gpu/nova-core/regs/macros.rs
>> @@ -0,0 +1,297 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +
>> +//! Types and macros to define register layout and accessors.
>> +//!
>> +//! A single register typically includes several fields, which are accessed through a combination
>> +//! of bit-shift and mask operations that introduce a class of potential mistakes, notably because
>> +//! not all possible field values are necessarily valid.
>> +//!
>> +//! The macros in this module allow to define, using an intruitive and readable syntax, a dedicated
>> +//! type for each register with its own field accessors that can return an error is a field's value
>> +//! is invalid. They also provide a builder type allowing to construct a register value to be
>> +//! written by combining valid values for its fields.
>> +
>> +/// Helper macro for the `register` macro.
>> +///
>> +/// Defines the wrapper `$name` type, as well as its relevant implementations (`Debug`, `BitOr`,
>> +/// and conversion to regular `u32`).
>> +macro_rules! __reg_def_common {
>> + ($name:ident $(, $type_comment:expr)?) => {
>> + $(
>> + #[doc=$type_comment]
>> + )?
>> + #[repr(transparent)]
>> + #[derive(Clone, Copy, Default)]
>> + pub(crate) struct $name(u32);
>> +
>> + // TODO: should we display the raw hex value, then the value of all its fields?
>
> To me it seems useful to have both.
Agreed. However this macro has changed A LOT since this first revision,
and I have used TT bundling to make the rules a bit shorter. This makes
the details of the fields inaccessible from the rule that generates the
Debug implementation...
I'll probably try to rework that later, or when we move the macro into
the kernel crate - meanwhile, I hope we can be excused with just the hex
value.
>
>> + impl ::core::fmt::Debug for $name {
>> + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
>> + f.debug_tuple(stringify!($name))
>> + .field(&format_args!("0x{0:x}", &self.0))
>> + .finish()
>> + }
>> + }
>> +
>> + impl core::ops::BitOr for $name {
>> + type Output = Self;
>> +
>> + fn bitor(self, rhs: Self) -> Self::Output {
>> + Self(self.0 | rhs.0)
>> + }
>> + }
>> +
>> + impl From<$name> for u32 {
>
> Here and in a few more cases below: This needs the full path; also remember to
> use absolute paths everwhere.
Indeed, thanks for the reminder. I hope I got them all.
>> + const MASK: u32 = ((((1 << $hi) - 1) << 1) + 1) - ((1 << $lo) - 1);
>> + const SHIFT: u32 = MASK.trailing_zeros();
>> + let field = (self.0 & MASK) >> SHIFT;
>> +
>> + $( field as $as_type )?
>> + $(
>> + // TODO: it would be nice to throw a compile-time error if $hi != $lo as this means we
>> + // are considering more than one bit but returning a bool...
>
> Would the following work?
>
> const _: () = {
> build_assert!($hi != $lo);
> ()
> };
It does! I can even provide a useful error message. Added this check as
well as the one making sure that $hi >= $lo.
>> +macro_rules! register {
>> + // Create a register at a fixed offset of the MMIO space.
>> + (
>> + $name:ident@$offset:expr $(, $type_comment:expr)?
>
> Can we use this as doc-comment?
Oops, I forgot to propagate it somehow. This is fixed.
>
>> + $(; $hi:tt:$lo:tt $field:ident
>> + $(=> as $as_type:ty)?
>> + $(=> as_bit $bit_type:ty)?
>> + $(=> into $type:ty)?
>> + $(=> try_into $try_type:ty)?
>> + $(, $field_comment:expr)?)* $(;)?
>> + ) => {
>> + __reg_def_common!($name);
>> +
>> + #[allow(dead_code)]
>> + impl $name {
>> + #[inline]
>> + pub(crate) fn read<const SIZE: usize, T: Deref<Target=Io<SIZE>>>(bar: &T) -> Self {
>
> Not necessarily a PCI bar, could be any I/O type.
Indeed, renamed to `io`.
>
>> + Self(bar.read32($offset))
>> + }
>> +
>> + #[inline]
>> + pub(crate) fn write<const SIZE: usize, T: Deref<Target=Io<SIZE>>>(self, bar: &T) {
>> + bar.write32(self.0, $offset)
>> + }
>> +
>> + #[inline]
>> + pub(crate) fn alter<const SIZE: usize, T: Deref<Target=Io<SIZE>>, F: FnOnce(Self) -> Self>(bar: &T, f: F) {
>> + let reg = f(Self::read(bar));
>> + reg.write(bar);
>> + }
>> + }
>> +
>> + __reg_def_getters!($name; $( $hi:$lo $field $(=> as $as_type)? $(=> as_bit $bit_type)? $(=> into $type)? $(=> try_into $try_type)? $(, $field_comment)? );*);
>> +
>> + __reg_def_setters!($name; $( $hi:$lo $field $(=> as $as_type)? $(=> as_bit $bit_type)? $(=> into $type)? $(=> try_into $try_type)? $(, $field_comment)? );*);
>> + };
>> +
>> + // Create a register at a relative offset from a base address.
>> + (
>> + $name:ident@+$offset:expr $(, $type_comment:expr)?
>> + $(; $hi:tt:$lo:tt $field:ident
>> + $(=> as $as_type:ty)?
>> + $(=> as_bit $bit_type:ty)?
>> + $(=> into $type:ty)?
>> + $(=> try_into $try_type:ty)?
>> + $(, $field_comment:expr)?)* $(;)?
>> + ) => {
>
> I assume this is for cases where we have multiple instances of the same
> controller, engine, etc. I think it would be good to add a small example for
> this one too.
I'll add one.
You probably won't recognize this macro in its next revision. I've
finally read the little book of Rust macros and hopefully it is looking
a bit better - the definition of register fields notable should feel
more natural. All in all I think it is definitely better, but that
doesn't necessarily means it will be easier to review. ^_^;
One note, as agreed on Zulip I will rename all the register names to
capital snake case and disable the `camel_case_types` lint on the `regs`
module, so we use the exact same names as OpenRM. I will also make sure
that the names of the fields match (but will keep the accessors in
non-capital snake case).
In parallel I am also prototyping another design based on ZST constants.
If it works it would allow a few more things like register arrays, a
more natural way to perform I/O, and would remove the naming convention
issues since registers would be accessed by constants which should be
named in capital snake-case anyway. My hope is that this version will be
the one we can use in the kernel crate, but I don't think it will be
ready before a couple of cycles at least (if it works at all), so in the
meantime let's keep refining this one.
Cheers,
Alex.
next prev parent reply other threads:[~2025-04-28 14:27 UTC|newest]
Thread overview: 60+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-04-20 12:19 [PATCH 00/16] nova-core: run FWSEC-FRTS to perform first stage of GSP initialization Alexandre Courbot
2025-04-20 12:19 ` [PATCH 01/16] rust: add useful ops for u64 Alexandre Courbot
2025-04-20 12:19 ` [PATCH 02/16] rust: make ETIMEDOUT error available Alexandre Courbot
2025-04-20 12:19 ` [PATCH 03/16] gpu: nova-core: derive useful traits for Chipset Alexandre Courbot
2025-04-22 16:23 ` Joel Fernandes
2025-04-24 7:50 ` Alexandre Courbot
2025-04-20 12:19 ` [PATCH 04/16] gpu: nova-core: add missing GA100 definition Alexandre Courbot
2025-04-20 12:19 ` [PATCH 05/16] gpu: nova-core: take bound device in Gpu::new Alexandre Courbot
2025-04-20 12:19 ` [PATCH 06/16] gpu: nova-core: define registers layout using helper macro Alexandre Courbot
2025-04-22 10:29 ` Danilo Krummrich
2025-04-28 14:27 ` Alexandre Courbot [this message]
2025-04-20 12:19 ` [PATCH 07/16] gpu: nova-core: move Firmware to firmware module Alexandre Courbot
2025-04-20 12:19 ` [PATCH 08/16] gpu: nova-core: wait for GFW_BOOT completion Alexandre Courbot
2025-04-21 21:45 ` Joel Fernandes
2025-04-22 11:28 ` Danilo Krummrich
2025-04-22 13:06 ` Alexandre Courbot
2025-04-22 13:46 ` Joel Fernandes
2025-04-22 11:36 ` Danilo Krummrich
2025-04-29 12:48 ` Alexandre Courbot
2025-04-30 22:45 ` Joel Fernandes
2025-04-20 12:19 ` [PATCH 09/16] gpu: nova-core: register sysmem flush page Alexandre Courbot
2025-04-22 11:45 ` Danilo Krummrich
2025-04-23 13:03 ` Alexandre Courbot
2025-04-22 18:50 ` Joel Fernandes
2025-04-20 12:19 ` [PATCH 10/16] gpu: nova-core: add basic timer device Alexandre Courbot
2025-04-22 12:07 ` Danilo Krummrich
2025-04-29 13:13 ` Alexandre Courbot
2025-04-20 12:19 ` [PATCH 11/16] gpu: nova-core: add falcon register definitions and base code Alexandre Courbot
2025-04-22 14:44 ` Danilo Krummrich
2025-04-30 6:58 ` Joel Fernandes
2025-04-30 10:32 ` Danilo Krummrich
2025-04-30 13:25 ` Alexandre Courbot
2025-04-30 14:38 ` Joel Fernandes
2025-04-30 18:16 ` Danilo Krummrich
2025-04-30 23:08 ` Joel Fernandes
2025-05-01 0:09 ` Alexandre Courbot
2025-05-01 0:22 ` Joel Fernandes
2025-05-01 14:07 ` Alexandre Courbot
2025-04-20 12:19 ` [PATCH 12/16] gpu: nova-core: firmware: add ucode descriptor used by FWSEC-FRTS Alexandre Courbot
2025-04-22 14:46 ` Danilo Krummrich
2025-04-20 12:19 ` [PATCH 13/16] gpu: nova-core: Add support for VBIOS ucode extraction for boot Alexandre Courbot
2025-04-23 14:06 ` Danilo Krummrich
2025-04-23 14:52 ` Joel Fernandes
2025-04-23 15:02 ` Danilo Krummrich
2025-04-24 19:19 ` Joel Fernandes
2025-04-24 20:01 ` Danilo Krummrich
2025-04-24 19:54 ` Joel Fernandes
2025-04-24 20:17 ` Danilo Krummrich
2025-04-25 2:32 ` [13/16] " Joel Fernandes
2025-04-25 17:10 ` Joel Fernandes
2025-04-24 18:54 ` [PATCH 13/16] " Joel Fernandes
2025-04-24 20:08 ` Danilo Krummrich
2025-04-25 2:26 ` [13/16] " Joel Fernandes
2025-04-24 20:22 ` [PATCH 13/16] " Joel Fernandes
2025-04-26 23:17 ` [13/16] " Joel Fernandes
2025-04-20 12:19 ` [PATCH 14/16] gpu: nova-core: compute layout of the FRTS region Alexandre Courbot
2025-04-20 12:19 ` [PATCH 15/16] gpu: nova-core: extract FWSEC from BIOS and patch it to run FWSEC-FRTS Alexandre Courbot
2025-04-20 12:19 ` [PATCH 16/16] gpu: nova-core: load and " Alexandre Courbot
2025-04-22 8:40 ` [PATCH 00/16] nova-core: run FWSEC-FRTS to perform first stage of GSP initialization Danilo Krummrich
2025-04-22 14:12 ` 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=D9ICBZ1DGGVU.2AKUD3X883TMB@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=benno.lossin@proton.me \
--cc=bjorn3_gh@protonmail.com \
--cc=boqun.feng@gmail.com \
--cc=bskeggs@nvidia.com \
--cc=corbet@lwn.net \
--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=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.