lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <1da3adab-f52c-461d-bd68-8623d6d7e223@de.bosch.com>
Date: Thu, 13 Nov 2025 07:26:46 +0100
From: Dirk Behme <dirk.behme@...bosch.com>
To: Alexandre Courbot <acourbot@...dia.com>, Dirk Behme
	<dirk.behme@...il.com>, Danilo Krummrich <dakr@...nel.org>, Joel Fernandes
	<joelagnelf@...dia.com>
CC: <linux-kernel@...r.kernel.org>, <rust-for-linux@...r.kernel.org>,
	<dri-devel@...ts.freedesktop.org>, Alistair Popple <apopple@...dia.com>,
	Miguel Ojeda <ojeda@...nel.org>, Alex Gaynor <alex.gaynor@...il.com>, "Boqun
 Feng" <boqun.feng@...il.com>, Gary Guo <gary@...yguo.net>,
	<bjorn3_gh@...tonmail.com>, Benno Lossin <lossin@...nel.org>, "Andreas
 Hindborg" <a.hindborg@...nel.org>, Alice Ryhl <aliceryhl@...gle.com>, "Trevor
 Gross" <tmgross@...ch.edu>, David Airlie <airlied@...il.com>, Simona Vetter
	<simona@...ll.ch>, Maarten Lankhorst <maarten.lankhorst@...ux.intel.com>,
	Maxime Ripard <mripard@...nel.org>, Thomas Zimmermann <tzimmermann@...e.de>,
	John Hubbard <jhubbard@...dia.com>, Timur Tabi <ttabi@...dia.com>,
	<joel@...lfernandes.org>, Elle Rhumsaa <elle@...thered-steel.dev>, Yury Norov
	<yury.norov@...il.com>, Daniel Almeida <daniel.almeida@...labora.com>,
	"Andrea Righi" <arighi@...dia.com>, <nouveau@...ts.freedesktop.org>,
	dri-devel <dri-devel-bounces@...ts.freedesktop.org>
Subject: Re: [PATCH v6 4/5] rust: Move register and bitfield macros out of
 Nova

On 02/11/2025 04:00, Alexandre Courbot wrote:
> On Sun Nov 2, 2025 at 3:51 AM JST, Dirk Behme wrote:
>> On 09.10.25 13:28, Alexandre Courbot wrote:
>>> On Thu Oct 9, 2025 at 8:16 PM JST, Danilo Krummrich wrote:
>>>> On Thu Oct 9, 2025 at 8:59 AM CEST, Dirk Behme wrote:
>>>>> Assuming that register.rs is supposed to become the "generic" way to
>>>>> access hardware registers I started to have a look to it. Some weeks
>>>>> back testing interrupts I used some quite simple timer with 4 registers
>>>>> [1]. Now, thinking about converting it to register!() I have three
>>>>> understanding / usage questions:
>>>>>
>>>>> * At the moment register!() is for 32-bit registers, only? So it can't
>>>>> be used for my example having 8-bit and 16-bit registers as well?
>>>>
>>>> Yes, currently the register!() macro always generates a 32-bit register type
>>>> (mainly because nova-core did not need anything else). However, this will of
>>>> course be generalized (which should be pretty straight forward).
>>>>
>>>> Having a brief look at the TMU datasheet it looks like you should be able to
>>>> treat TSTR and TCR as 32-bit registers without any issues for testing the
>>>> register!() macro today. I.e. you can just define it as:
>>>>
>>>> 	register!(TSTR @ 0x04, "Timer Start Register" {
>>>> 	    2:2    str2 as bool, "Specifies whether TCNT2 is operated or stopped.";
>>>> 	    1:1    str1 as bool, "Specifies whether TCNT1 is operated or stopped.";
>>>> 	    0:0    str0 as bool, "Specifies whether TCNT0 is operated or stopped.";
>>>> 	});
>>>>
>>>> Same for TCR.
>>>
>>> Patch 2 of this series actually adds support for 16 and 8 bit register
>>> storage.
>>
>> Hmm, how to use that with the register!() macro? I mean patch 2 adds
>> support for different storage widths for *bitfields*. But looking at
>> patch 4 [2] it looks like *register!()* still uses $name(u32)? With
>> that it looks like that the register!() macro still just supports 32
>> bit registers? Or what have I missed?
>>
>> What I'm looking for is a way to specify if a register is 8, 16 or 32
>> bit. Using the example from above something like
>>
>> register!(TSTR<u8> @ ....
> 
> Errr indeed, you are correct. The `register` macro's syntax has not been
> updated to take advantage of `bitfield`'s storage types, and `u32` is
> still hardcoded as of this series.
> 
> This looks like an oversight - a register is basically a bitfield with
> some I/O, so making it support storage types should be trivial. I guess
> this hasn't been done yet because Nova is the only user so far, and we
> don't need/want to explicitly specify a type for each register since
> they are invariably `u32`.
> 
> But it wouldn't look good to change the syntax of `register` after
> moving it out, so I agree this should take place before the move. The
> same applies to the visiblity feature.
> 
> One way to avoid a update all the declarations so far would be to give
> Nova its own `register` macro that invokes the one in `kernel` with
> the relevant parameters hardcoded.


Just fyi, hacking something like [1] below does work for my (very 
limited) use case. And it defaults `register!` without type to <u32>.

Thanks!

Dirk

[1]

--- a/rust/kernel/io/register.rs
+++ b/rust/kernel/io/register.rs
@@ -276,33 +276,38 @@ pub trait RegisterBase<T> {
  /// ```
  #[macro_export]
  macro_rules! register {
-    // Creates a register at a fixed offset of the MMIO space.
+    // Creates a register at a fixed offset of the MMIO space, defaults 
to u32 if no type is specified.
      ($name:ident @ $offset:literal $(, $comment:literal)? { 
$($fields:tt)* } ) => {
-        ::kernel::bitfield!(pub(crate) struct $name(u32) $(, $comment)? 
{ $($fields)* } );
-        register!(@io_fixed $name @ $offset);
+        register!($name<u32> @ $offset $(, $comment)? { $($fields)* });
+    };
+
+    // Creates a register at a fixed offset of the MMIO space, explicit 
type required.
+    ($name:ident<$ty:ty> @ $offset:literal $(, $comment:literal)? { 
$($fields:tt)* } ) => {
+        ::kernel::bitfield!(pub(crate) struct $name($ty) $(, $comment)? 
{ $($fields)* } );
+        register!(@io_fixed<$ty> $name @ $offset);
      };

      // Creates an alias register of fixed offset register `alias` with 
its own fields.
-    ($name:ident => $alias:ident $(, $comment:literal)? { 
$($fields:tt)* } ) => {
-        ::kernel::bitfield!(pub(crate) struct $name(u32) $(, $comment)? 
{ $($fields)* } );
-        register!(@io_fixed $name @ $alias::OFFSET);
+    ($name:ident<$ty:ty> => $alias:ident $(, $comment:literal)? { 
$($fields:tt)* } ) => {
+        ::kernel::bitfield!(pub(crate) struct $name($ty) $(, $comment)? 
{ $($fields)* } );
+        register!(@io_fixed<$ty> $name @ $alias::OFFSET);
      };

      // Creates a register at a relative offset from a base address 
provider.
-    ($name:ident @ $base:ty [ $offset:literal ] $(, $comment:literal)? 
{ $($fields:tt)* } ) => {
-        ::kernel::bitfield!(pub(crate) struct $name(u32) $(, $comment)? 
{ $($fields)* } );
-        register!(@io_relative $name @ $base [ $offset ]);
+    ($name:ident<$ty:ty> @ $base:ty [ $offset:literal ] $(, 
$comment:literal)? { $($fields:tt)* } ) => {
+        ::kernel::bitfield!(pub(crate) struct $name($ty) $(, $comment)? 
{ $($fields)* } );
+        register!(@io_relative<$ty> $name @ $base [ $offset ]);
      };

      // Creates an alias register of relative offset register `alias` 
with its own fields.
-    ($name:ident => $base:ty [ $alias:ident ] $(, $comment:literal)? { 
$($fields:tt)* }) => {
-        ::kernel::bitfield!(pub(crate) struct $name(u32) $(, $comment)? 
{ $($fields)* } );
-        register!(@io_relative $name @ $base [ $alias::OFFSET ]);
+    ($name:ident<$ty:ty> => $base:ty [ $alias:ident ] $(, 
$comment:literal)? { $($fields:tt)* }) => {
+        ::kernel::bitfield!(pub(crate) struct $name($ty) $(, $comment)? 
{ $($fields)* } );
+        register!(@io_relative<$ty> $name @ $base [ $alias::OFFSET ]);
      };

-    // Creates an array of registers at a fixed offset of the MMIO space.
+    // Creates an array of registers at a fixed offset of the MMIO 
space. (u32 only for now)
      (
-        $name:ident @ $offset:literal [ $size:expr ; $stride:expr ] $(, 
$comment:literal)? {
+        $name:ident<u32> @ $offset:literal [ $size:expr ; $stride:expr 
] $(, $comment:literal)? {
              $($fields:tt)*
          }
      ) => {
@@ -311,20 +316,20 @@ macro_rules! register {
          register!(@io_array $name @ $offset [ $size ; $stride ]);
      };

-    // Shortcut for contiguous array of registers (stride == size of 
element).
+    // Shortcut for contiguous array of registers (stride == size of 
element). (u32 only for now)
      (
-        $name:ident @ $offset:literal [ $size:expr ] $(, 
$comment:literal)? {
+        $name:ident<u32> @ $offset:literal [ $size:expr ] $(, 
$comment:literal)? {
              $($fields:tt)*
          }
      ) => {
-        register!($name @ $offset [ $size ; 
::core::mem::size_of::<u32>() ] $(, $comment)? {
+        register!($name<u32> @ $offset [ $size ; 
::core::mem::size_of::<u32>() ] $(, $comment)? {
              $($fields)*
          } );
      };

-    // Creates an array of registers at a relative offset from a base 
address provider.
+    // Creates an array of registers at a relative offset from a base 
address provider. (u32 only for now)
      (
-        $name:ident @ $base:ty [ $offset:literal [ $size:expr ; 
$stride:expr ] ]
+        $name:ident<u32> @ $base:ty [ $offset:literal [ $size:expr ; 
$stride:expr ] ]
              $(, $comment:literal)? { $($fields:tt)* }
      ) => {
          static_assert!(::core::mem::size_of::<u32>() <= $stride);
@@ -332,20 +337,19 @@ macro_rules! register {
          register!(@io_relative_array $name @ $base [ $offset [ $size ; 
$stride ] ]);
      };

-    // Shortcut for contiguous array of relative registers (stride == 
size of element).
+    // Shortcut for contiguous array of relative registers (stride == 
size of element). (u32 only for now)
      (
-        $name:ident @ $base:ty [ $offset:literal [ $size:expr ] ] $(, 
$comment:literal)? {
+        $name:ident<u32> @ $base:ty [ $offset:literal [ $size:expr ] ] 
$(, $comment:literal)? {
              $($fields:tt)*
          }
      ) => {
-        register!($name @ $base [ $offset [ $size ; 
::core::mem::size_of::<u32>() ] ]
+        register!($name<u32> @ $base:ty [ $offset:literal [ $size:expr 
; ::core::mem::size_of::<u32>() ] ]
              $(, $comment)? { $($fields)* } );
      };

-    // Creates an alias of register `idx` of relative array of 
registers `alias` with its own
-    // fields.
+    // Creates an alias of register `idx` of relative array of 
registers `alias` with its own fields. (u32 only for now)
      (
-        $name:ident => $base:ty [ $alias:ident [ $idx:expr ] ] $(, 
$comment:literal)? {
+        $name:ident<u32> => $base:ty [ $alias:ident [ $idx:expr ] ] $(, 
$comment:literal)? {
              $($fields:tt)*
          }
      ) => {
@@ -354,17 +358,15 @@ macro_rules! register {
          register!(@io_relative $name @ $base [ $alias::OFFSET + $idx * 
$alias::STRIDE ] );
      };

-    // Creates an alias of register `idx` of array of registers `alias` 
with its own fields.
-    // This rule belongs to the (non-relative) register arrays set, but 
needs to be put last
-    // to avoid it being interpreted in place of the relative register 
array alias rule.
-    ($name:ident => $alias:ident [ $idx:expr ] $(, $comment:literal)? { 
$($fields:tt)* }) => {
+    // Creates an alias of register `idx` of array of registers `alias` 
with its own fields. (u32 only for now)
+    ($name:ident<u32> => $alias:ident [ $idx:expr ] $(, 
$comment:literal)? { $($fields:tt)* }) => {
          static_assert!($idx < $alias::SIZE);
          ::kernel::bitfield!(pub(crate) struct $name(u32) $(, 
$comment)? { $($fields)* } );
          register!(@io_fixed $name @ $alias::OFFSET + $idx * 
$alias::STRIDE );
      };

-    // Generates the IO accessors for a fixed offset register.
-    (@io_fixed $name:ident @ $offset:expr) => {
+    // Generates the IO accessors for a fixed offset register, using 
the type parameter.
+    (@io_fixed<$ty:ty> $name:ident @ $offset:expr) => {
          #[allow(dead_code)]
          impl $name {
              pub(crate) const OFFSET: usize = $offset;
@@ -374,7 +376,15 @@ impl $name {
              pub(crate) fn read<const SIZE: usize, T>(io: &T) -> Self where
                  T: ::core::ops::Deref<Target = ::kernel::io::Io<SIZE>>,
              {
-                Self(io.read32($offset))
+                Self(
+                    if core::any::TypeId::of::<$ty>() == 
core::any::TypeId::of::<u8>() {
+                        io.read8($offset) as $ty
+                    } else if core::any::TypeId::of::<$ty>() == 
core::any::TypeId::of::<u16>() {
+                        io.read16($offset) as $ty
+                    } else {
+                        io.read32($offset) as $ty
+                    }
+                )
              }

              /// Write the value contained in `self` to the register 
address in `io`.
@@ -382,7 +392,13 @@ pub(crate) fn read<const SIZE: usize, T>(io: &T) -> 
Self where
              pub(crate) fn write<const SIZE: usize, T>(self, io: &T) where
                  T: ::core::ops::Deref<Target = ::kernel::io::Io<SIZE>>,
              {
-                io.write32(self.0, $offset)
+                if core::any::TypeId::of::<$ty>() == 
core::any::TypeId::of::<u8>() {
+                    io.write8(self.0 as u8, $offset)
+                } else if core::any::TypeId::of::<$ty>() == 
core::any::TypeId::of::<u16>() {
+                    io.write16(self.0 as u16, $offset)
+                } else {
+                    io.write32(self.0 as u32, $offset)
+                }
              }

              /// Read the register from its address in `io` and run `f` 
on its value to obtain a new
@@ -401,8 +417,8 @@ pub(crate) fn alter<const SIZE: usize, T, F>(
          }
      };

-    // Generates the IO accessors for a relative offset register.
-    (@io_relative $name:ident @ $base:ty [ $offset:expr ]) => {
+    // Generates the IO accessors for a relative offset register, using 
the type parameter.
+    (@io_relative<$ty:ty> $name:ident @ $base:ty [ $offset:expr ]) => {
          #[allow(dead_code)]
          impl $name {
              pub(crate) const OFFSET: usize = $offset;
@@ -420,9 +436,7 @@ pub(crate) fn read<const SIZE: usize, T, B>(
              {
                  const OFFSET: usize = $name::OFFSET;

-                let value = io.read32(
-                    <B as 
::kernel::io::register::RegisterBase<$base>>::BASE + OFFSET
-                );
+                let value = io.read::<$ty>(<B as 
::kernel::io::register::RegisterBase<$base>>::BASE + OFFSET);

                  Self(value)
              }
@@ -441,10 +455,7 @@ pub(crate) fn write<const SIZE: usize, T, B>(
              {
                  const OFFSET: usize = $name::OFFSET;

-                io.write32(
-                    self.0,
-                    <B as 
::kernel::io::register::RegisterBase<$base>>::BASE + OFFSET
-                );
+                io.write::<$ty>(self.0, <B as 
::kernel::io::register::RegisterBase<$base>>::BASE + OFFSET);
              }

              /// Read the register from `io`, using the base address 
provided by `base` and adding
-- 
2.48.0

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ