From: Joel Fernandes <joelagnelf@nvidia.com>
To: linux-kernel@vger.kernel.org
Cc: Miguel Ojeda <ojeda@kernel.org>, Boqun Feng <boqun@kernel.org>,
Gary Guo <gary@garyguo.net>,
Bjorn 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>,
Danilo Krummrich <dakr@kernel.org>,
Dave Airlie <airlied@redhat.com>,
Daniel Almeida <daniel.almeida@collabora.com>,
dri-devel@lists.freedesktop.org, rust-for-linux@vger.kernel.org,
nova-gpu@lists.linux.dev, Nikola Djukic <ndjukic@nvidia.com>,
David Airlie <airlied@gmail.com>,
Boqun Feng <boqun.feng@gmail.com>,
John Hubbard <jhubbard@nvidia.com>,
Alistair Popple <apopple@nvidia.com>,
Timur Tabi <ttabi@nvidia.com>, Edwin Peer <epeer@nvidia.com>,
Alexandre Courbot <acourbot@nvidia.com>,
Andrea Righi <arighi@nvidia.com>,
Andy Ritger <aritger@nvidia.com>, Zhi Wang <zhiw@nvidia.com>,
Balbir Singh <balbirs@nvidia.com>,
Philipp Stanner <phasta@kernel.org>,
alexeyi@nvidia.com, Eliot Courtney <ecourtney@nvidia.com>,
joel@joelfernandes.org, linux-doc@vger.kernel.org,
Joel Fernandes <joelagnelf@nvidia.com>
Subject: [PATCH v1 02/12] rust: bitfield: support cast+shift accessor syntax
Date: Mon, 18 May 2026 14:03:32 -0400 [thread overview]
Message-ID: <20260518180342.2387845-3-joelagnelf@nvidia.com> (raw)
In-Reply-To: <20260518180342.2387845-1-joelagnelf@nvidia.com>
The `bitfield!` macro previously generated accessors that returned the
field's value as a `Bounded<$storage, N>` for its raw N-bit width. For
fields whose logical interpretation is a wider value built by widening
the storage type and shifting left (e.g., a 24-bit register field that
stores bits 16..40 of a 40-bit address), callers had to chain
`cast::<TargetType>()` and `shl::<SHIFT, RES>()` (or worse, raw shift
operators) at every read site, and the inverse for writes.
Add a new field declaration shape:
$hi:$lo $field as Bounded<$target, $res> shl $shift;
The macro generates:
- A getter `$field(self) -> Bounded<$target, $res>` that extracts the
raw N-bit field, widens it to $target, and shifts left by $shift.
- A setter `with_$field(self, value: Bounded<$target, $res>) -> Self`
that shifts right by $shift, narrows to the storage type, and writes.
Add a KUnit test mirroring nova-core driver's PRAMIN window register
pattern as well which is the usecase for it.
Signed-off-by: Joel Fernandes <joelagnelf@nvidia.com>
---
rust/kernel/bitfield.rs | 67 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 67 insertions(+)
diff --git a/rust/kernel/bitfield.rs b/rust/kernel/bitfield.rs
index 9ab8dafff36c..1c1fc86441f2 100644
--- a/rust/kernel/bitfield.rs
+++ b/rust/kernel/bitfield.rs
@@ -57,6 +57,8 @@
//! hi:lo field_2 => ConvertedType;
//! // `field_3` documentation.
//! hi:lo field_3 ?=> ConvertedType;
+//! // `field_4` documentation.
+//! hi:lo field_4 as Bounded<TargetType, RES> shl SHIFT;
//! ...
//! }
//! }
@@ -66,6 +68,8 @@
//! - `hi:lo`: Bit range (inclusive), where `hi >= lo`.
//! - `=> Type`: Optional infallible conversion (see [below](#infallible-conversion-)).
//! - `?=> Type`: Optional fallible conversion (see [below](#fallible-conversion-)).
+//! - `as Bounded<T, RES> shl SHIFT`: Optional cast-and-shift accessor (see
+//! [below](#cast-and-shift-accessors-as-bounded-t-res-shl-shift)).
//! - Documentation strings and attributes are optional.
//!
//! # Generated code
@@ -299,6 +303,7 @@ fn from(val: $storage) -> $name {
$($(#[doc = $doc:expr])* $hi:literal:$lo:literal $field:ident
$(?=> $try_into_type:ty)?
$(=> $into_type:ty)?
+ $(as Bounded<$target:ty, $res:literal> shl $shift:literal)?
;
)*
}
@@ -311,6 +316,7 @@ impl $name {
@public_field_accessors $(#[doc = $doc])* $vis $name $storage : $hi:$lo $field
$(?=> $try_into_type)?
$(=> $into_type)?
+ $(as Bounded<$target, $res> shl $shift)?
);
)*
}
@@ -475,6 +481,43 @@ const fn [<__with_ $field>](
);
};
+ // Public accessors for fields cast to a wider type and left-shifted, exposing them as
+ // `Bounded<$target, $res>` where `$res == ($hi + 1 - $lo) + $shift`.
+ (
+ @public_field_accessors $(#[doc = $doc:expr])* $vis:vis $name:ident $storage:ty :
+ $hi:literal:$lo:literal $field:ident
+ as Bounded<$target:ty, $res:literal> shl $shift:literal
+ ) => {
+ ::kernel::macros::paste!(
+
+ $(#[doc = $doc])*
+ #[doc = "Returns the value of this field, cast to the target type and shifted left."]
+ #[inline(always)]
+ $vis fn $field(self) -> ::kernel::num::Bounded<$target, $res> {
+ $crate::const_assert!($res == ($hi + 1 - $lo) + $shift);
+
+ self.[<__ $field>]()
+ .cast::<$target>()
+ .shl::<$shift, $res>()
+ }
+
+ $(#[doc = $doc])*
+ #[doc = "Sets this field from a target-typed, pre-shifted `Bounded` value."]
+ #[inline(always)]
+ $vis fn [<with_ $field>](
+ self,
+ value: ::kernel::num::Bounded<$target, $res>,
+ ) -> Self {
+ $crate::const_assert!($res == ($hi + 1 - $lo) + $shift);
+
+ self.[<__with_ $field>](
+ value.shr::<$shift, { $hi + 1 - $lo }>().cast::<$storage>()
+ )
+ }
+
+ );
+ };
+
// `Debug` implementation.
(@debug $name:ident { $($field:ident;)* }) => {
impl ::kernel::fmt::Debug for $name {
@@ -582,6 +625,15 @@ struct TestStatusRegister(u8) {
}
}
+ // Mirrors the PRAMIN window register pattern: a 24-bit field in a `u32` storage that
+ // represents bits 16..40 of a 40-bit address. The accessor exposes it as the full
+ // 40-bit `Bounded<u64, 40>`.
+ bitfield! {
+ struct TestWindowReg(u32) {
+ 23:0 window_base as Bounded<u64, 40> shl 16;
+ }
+ }
+
#[test]
fn test_single_bits() {
let mut pte = TestPageTableEntry::zeroed();
@@ -806,4 +858,19 @@ fn test_u8_bitfield() {
assert_eq!(status4.reserved(), 0xF);
assert_eq!(status4.full_byte(), 0xFF);
}
+
+ #[test]
+ fn test_cast_shift_accessor() {
+ // Set a value via the pre-shifted setter and read it back via the getter.
+ let addr = Bounded::<u64, 40>::new::<0x12_3456_0000>();
+ let reg = TestWindowReg::zeroed().with_window_base(addr);
+ assert_eq!(reg.window_base().get(), 0x12_3456_0000u64);
+ assert_eq!(u32::from(reg), 0x0012_3456u32);
+
+ // Setting and reading the largest 40-bit aligned value.
+ let max_addr = Bounded::<u64, 40>::new::<0xFF_FFFF_0000>();
+ let reg = TestWindowReg::zeroed().with_window_base(max_addr);
+ assert_eq!(reg.window_base().get(), 0xFF_FFFF_0000u64);
+ assert_eq!(u32::from(reg), 0x00FF_FFFFu32);
+ }
}
--
2.34.1
next prev parent reply other threads:[~2026-05-18 18:03 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-18 18:03 [PATCH v1 00/12] Introduce nova-core mm prerequisites Joel Fernandes
2026-05-18 18:03 ` [PATCH v1 01/12] rust: pci: add resource_flags accessor Joel Fernandes
2026-05-18 18:03 ` Joel Fernandes [this message]
2026-05-18 18:03 ` [PATCH v1 03/12] gpu: nova-core: gsp: Return GspStaticInfo from boot() Joel Fernandes
2026-05-18 18:03 ` [PATCH v1 04/12] gpu: nova-core: gsp: Extract usable FB region from GSP Joel Fernandes
2026-05-18 18:03 ` [PATCH v1 05/12] gpu: nova-core: gsp: Expose total physical VRAM end from FB region info Joel Fernandes
2026-05-18 18:03 ` [PATCH v1 06/12] gpu: nova-core: mm: Add Pfn (Physical Frame Number) type Joel Fernandes
2026-05-18 18:03 ` [PATCH v1 07/12] gpu: nova-core: mm: Add VramAddress type and conversion traits Joel Fernandes
2026-05-18 18:03 ` [PATCH v1 08/12] gpu: nova-core: mm: Add VramAddress arithmetic and ordering Joel Fernandes
2026-05-18 18:03 ` [PATCH v1 09/12] gpu: nova-core: mm: Add support to use PRAMIN windows to write to VRAM Joel Fernandes
2026-05-18 18:03 ` [PATCH v1 10/12] docs: gpu: nova-core: Document the PRAMIN aperture mechanism Joel Fernandes
2026-05-18 18:03 ` [PATCH v1 11/12] gpu: nova-core: mm: Add GpuMm centralized memory manager Joel Fernandes
2026-05-18 18:03 ` [PATCH v1 12/12] gpu: nova-core: mm: Add PRAMIN aperture self-tests 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=20260518180342.2387845-3-joelagnelf@nvidia.com \
--to=joelagnelf@nvidia.com \
--cc=a.hindborg@kernel.org \
--cc=acourbot@nvidia.com \
--cc=airlied@gmail.com \
--cc=airlied@redhat.com \
--cc=alexeyi@nvidia.com \
--cc=aliceryhl@google.com \
--cc=apopple@nvidia.com \
--cc=arighi@nvidia.com \
--cc=aritger@nvidia.com \
--cc=balbirs@nvidia.com \
--cc=bjorn3_gh@protonmail.com \
--cc=boqun.feng@gmail.com \
--cc=boqun@kernel.org \
--cc=dakr@kernel.org \
--cc=daniel.almeida@collabora.com \
--cc=dri-devel@lists.freedesktop.org \
--cc=ecourtney@nvidia.com \
--cc=epeer@nvidia.com \
--cc=gary@garyguo.net \
--cc=jhubbard@nvidia.com \
--cc=joel@joelfernandes.org \
--cc=linux-doc@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=lossin@kernel.org \
--cc=ndjukic@nvidia.com \
--cc=nova-gpu@lists.linux.dev \
--cc=ojeda@kernel.org \
--cc=phasta@kernel.org \
--cc=rust-for-linux@vger.kernel.org \
--cc=tmgross@umich.edu \
--cc=ttabi@nvidia.com \
--cc=zhiw@nvidia.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox