All of lore.kernel.org
 help / color / mirror / Atom feed
From: Alistair Popple <apopple@nvidia.com>
To: Alexandre Courbot <acourbot@nvidia.com>
Cc: "Miguel Ojeda" <ojeda@kernel.org>,
	"Danilo Krummrich" <dakr@kernel.org>,
	"Alice Ryhl" <aliceryhl@google.com>,
	"Nicolás Antinori" <nico.antinori.7@gmail.com>,
	"David Airlie" <airlied@gmail.com>,
	"Shuah Khan" <skhan@linuxfoundation.org>,
	"Simona Vetter" <simona@ffwll.ch>, "Gary Guo" <gary@garyguo.net>,
	"Onur Özkan" <work@onurozkan.dev>,
	"Tamir Duberstein" <tamird@kernel.org>,
	"Trevor Gross" <tmgross@umich.edu>,
	"Pedro Yudi Honda" <niyudi.honda@usp.br>,
	"SeungJong Ha" <engineer.jjhama@gmail.com>,
	linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org,
	rust-for-linux@vger.kernel.org, nova-gpu@lists.linux.de
Subject: Re: [PATCH 1/1] nova-core: Update firmware bindings to use zerocopy traits
Date: Mon, 29 Jun 2026 17:56:50 +1000	[thread overview]
Message-ID: <akIiunspnSSbGWoZ@nvdebian.thelocal> (raw)
In-Reply-To: <DJLD0BCHI6LK.20SNCG6M3E1D1@nvidia.com>

On 2026-06-29 at 17:36 +1000, Alexandre Courbot <acourbot@nvidia.com> wrote...
> On Mon Jun 29, 2026 at 11:52 AM JST, Alistair Popple wrote:
> > Currently most of nova-core uses unsafe implementations of AsBytes and
> > FromBytes in order to read and write GSP commands using the generated
> > bindings. Whilst this is generally safe in practice there is nothing
> > that actually guarantees or checks this.
> >
> > This is exactly what the zerocopy library was introduced to do - provide
> > compile-time checks ensuring From/AsBytes is safe. Make use of these
> > checks by converting all our generated bindings to derive the required
> > traits for the zerocopy checks, removing many unsafe implementations in
> > the process.
> >
> > Note this does require the use of an unstable feature - trivial_bounds
> > - as some bindings end up needing to derive zerocopy::Unaligned.
> > A work-around is also required in the bindings to make some of the
> > __IncompleteArrayField<T> ZSTs monomorphic as the check macro can not
> > prove a generic type is aligned and thus forces T to derive
> > zerocopy::Unaligned, which is not satisfied by all types.
> >
> > Signed-off-by: Alistair Popple <apopple@nvidia.com>
> 
> I have counted and this removes 28 unsafe statements. :) (it also adds
> 2 tbf)
> 
> > ---
> >  drivers/gpu/nova-core/Makefile                |   4 +
> >  drivers/gpu/nova-core/gsp/cmdq.rs             |  21 +-
> >  .../gpu/nova-core/gsp/cmdq/continuation.rs    |  16 +-
> >  drivers/gpu/nova-core/gsp/commands.rs         |  19 +-
> >  drivers/gpu/nova-core/gsp/fw.rs               |  54 +----
> >  drivers/gpu/nova-core/gsp/fw/commands.rs      |  50 ++---
> >  drivers/gpu/nova-core/gsp/fw/r570_144.rs      |  41 ++++
> >  .../gpu/nova-core/gsp/fw/r570_144/bindings.rs | 185 ++++++++++++------
> >  drivers/gpu/nova-core/gsp/sequencer.rs        |   5 +-
> >  scripts/Makefile.build                        |   4 +-
> >  10 files changed, 223 insertions(+), 176 deletions(-)
> >
> > diff --git a/drivers/gpu/nova-core/Makefile b/drivers/gpu/nova-core/Makefile
> > index 4ae544f808f4..27a5752c4cf9 100644
> > --- a/drivers/gpu/nova-core/Makefile
> > +++ b/drivers/gpu/nova-core/Makefile
> > @@ -1,4 +1,8 @@
> >  # SPDX-License-Identifier: GPL-2.0
> >  
> > +# The GSP firmware bindings derive zerocopy's `IntoBytes` on `#[repr(C)]`
> > +# unions, which is gated behind the `zerocopy_derive_union_into_bytes` cfg.
> > +rustflags-y += --cfg zerocopy_derive_union_into_bytes
> > +
> >  obj-$(CONFIG_NOVA_CORE) += nova-core.o
> >  nova-core-y := nova_core.o
> > diff --git a/drivers/gpu/nova-core/gsp/cmdq.rs b/drivers/gpu/nova-core/gsp/cmdq.rs
> > index 0671ee8a9960..6e79ec688983 100644
> > --- a/drivers/gpu/nova-core/gsp/cmdq.rs
> > +++ b/drivers/gpu/nova-core/gsp/cmdq.rs
> > @@ -29,6 +29,14 @@
> >      },
> >  };
> >  
> > +// TODO: Remove `as` once FromBytes is removed completely
> > +use zerocopy::{
> > +    FromBytes as ZCFromBytes,
> 
> Since zerocopy's `FromBytes` is the one we will keep long-term, should
> we rather rename the one from `transmute`?

Good idea - it ended up this way because I was going to split the series up to
convert one type at a time but ended up squashing it into one big change given
the mechanical nature of the conversions.

> <...>
> > --- a/drivers/gpu/nova-core/gsp/fw/r570_144.rs
> > +++ b/drivers/gpu/nova-core/gsp/fw/r570_144.rs
> > @@ -23,9 +23,50 @@
> >  )]
> >  use kernel::ffi;
> >  use pin_init::MaybeZeroable;
> > +use zerocopy_derive::{
> > +    FromBytes,
> > +    Immutable,
> > +    IntoBytes,
> > +    KnownLayout, //
> > +};
> >  
> >  include!("r570_144/bindings.rs");
> >  
> >  // SAFETY: This type has a size of zero, so its inclusion into another type should not affect their
> >  // ability to implement `Zeroable`.
> >  unsafe impl<T> kernel::prelude::Zeroable for __IncompleteArrayField<T> {}
> > +
> > +/// Monomorphic version of [`__IncompleteArrayField<PACKED_REGISTRY_ENTRY>`].
> > +///
> > +/// zerocopy's `IntoBytes` derive can only run its compile-time no-padding check
> > +/// on a concrete type; for the generic `__IncompleteArrayField<T>` it falls back
> > +/// to requiring every field be `Unaligned`, which `PACKED_REGISTRY_ENTRY`
> > +/// does not satisfy. Specializing to a concrete type lets the derive succeed.
> > +#[repr(C)]
> > +#[derive(Debug, Default, FromBytes, Immutable, IntoBytes, KnownLayout, MaybeZeroable)]
> > +pub struct __IncompletePackedRegistryEntry(
> > +    ::core::marker::PhantomData<PACKED_REGISTRY_ENTRY>,
> > +    [PACKED_REGISTRY_ENTRY; 0],
> > +);
> > +impl __IncompletePackedRegistryEntry {
> > +    #[inline]
> > +    pub const fn new() -> Self {
> > +        __IncompletePackedRegistryEntry(::core::marker::PhantomData, [])
> > +    }
> > +    #[inline]
> > +    pub fn as_ptr(&self) -> *const PACKED_REGISTRY_ENTRY {
> > +        self as *const _ as *const PACKED_REGISTRY_ENTRY
> > +    }
> > +    #[inline]
> > +    pub fn as_mut_ptr(&mut self) -> *mut PACKED_REGISTRY_ENTRY {
> > +        self as *mut _ as *mut PACKED_REGISTRY_ENTRY
> > +    }
> > +    #[inline]
> > +    pub unsafe fn as_slice(&self, len: usize) -> &[PACKED_REGISTRY_ENTRY] {
> > +        ::core::slice::from_raw_parts(self.as_ptr(), len)
> > +    }
> > +    #[inline]
> > +    pub unsafe fn as_mut_slice(&mut self, len: usize) -> &mut [PACKED_REGISTRY_ENTRY] {
> > +        ::core::slice::from_raw_parts_mut(self.as_mut_ptr(), len)
> > +    }
> > +}
> 
> Yikes, this is a one-shot so I guess we can live with that if neeeded.

Yes, this is a total hack but I couldn't figure out a better alternative.
Given this is the only type that has this problem I figured it was a bearable
trade-off to make, but am open to better suggestions if there are any.

> > diff --git a/drivers/gpu/nova-core/gsp/fw/r570_144/bindings.rs b/drivers/gpu/nova-core/gsp/fw/r570_144/bindings.rs
> > index ea350f9b2cc4..9c85c93f6eee 100644
> > --- a/drivers/gpu/nova-core/gsp/fw/r570_144/bindings.rs
> > +++ b/drivers/gpu/nova-core/gsp/fw/r570_144/bindings.rs
> > @@ -1,7 +1,7 @@
> >  // SPDX-License-Identifier: GPL-2.0
> >  
> >  #[repr(C)]
> > -#[derive(Default)]
> > +#[derive(Default, FromBytes, IntoBytes, Immutable, KnownLayout)]
> 
> This is the part my other email [1] was about: are we going, long-term,
> to replace this with a `#[derive(zerocopy_derive::most_traits)]`? If the
> Nova's bindings generator program can take care of producing the correct
> traits for each generated type then maybe that's even better, but at the
> same time I am wondering whether the kernel's bindgen invocation isn't
> going to automatically derive `most_traits` on all generated types. In
> this case, we could end up with duplicate implementations.

If that's coming soon I think it makes sense to wait simply to avoid churn
on the generated bindings. I didn't do anything too smart for Nova's binding
generator - it basically just derives all these traits for all our bindings.
Being able to have it derive `most_traits` would be cleaner. So happy to rebase
once that is merged.

> I think this point needs to be clarified before we can decide when to
> merge this patch.
> 
> [1] https://lore.kernel.org/all/DJLCF3LR0KMN.1TMKMZEZWKN8O@nvidia.com/
> 
> <...>
> >  #[repr(C)]
> > -#[derive(Debug, Default, MaybeZeroable)]
> > +#[derive(Debug, Default, MaybeZeroable, FromBytes, Immutable, KnownLayout, IntoBytes)]
> >  pub struct PACKED_REGISTRY_TABLE {
> >      pub size: u32_,
> >      pub numEntries: u32_,
> > -    pub entries: __IncompleteArrayField<PACKED_REGISTRY_ENTRY>,
> > +    pub entries: __IncompletePackedRegistryEntry,
> 
> This is part of the generated bindings, right? How does the generator
> program know it needs to use `__IncompletePackedRegistryEntry`?

Maigc[1] ... otherwise known as `sed` :-)

[1] - https://github.com/apopple-nvidia/nova-gsp-binding-generator/blob/zerocopy/Kbuild#L153

> <...>
> > --- a/scripts/Makefile.build
> > +++ b/scripts/Makefile.build
> > @@ -314,10 +314,12 @@ $(obj)/%.lst: $(obj)/%.c FORCE
> >  #   - Stable since Rust 1.89.0: `feature(generic_arg_infer)`.
> >  #   - Expected to become stable: `feature(arbitrary_self_types)`.
> >  #   - To be determined: `feature(used_with_arg)`.
> > +#   - Required by nova-core's zerocopy firmware bindings, whose derives emit
> > +#     trivial `where` bounds: `feature(trivial_bounds)`.
> >  #
> >  # Please see https://github.com/Rust-for-Linux/linux/issues/2 for details on
> >  # the unstable features in use.
> > -rust_allowed_features := arbitrary_self_types,asm_goto,generic_arg_infer,used_with_arg
> > +rust_allowed_features := arbitrary_self_types,asm_goto,generic_arg_infer,used_with_arg,trivial_bounds
> 
> This also might be something that will land soon through the Rust tree;
> Miguel, do you know what the plan is by any chance?

  reply	other threads:[~2026-06-29  7:57 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-06-29  2:52 [PATCH 0/1] nova-core: Convert bindings to use zerocopy Alistair Popple
2026-06-29  2:52 ` [PATCH 1/1] nova-core: Update firmware bindings to use zerocopy traits Alistair Popple
2026-06-29  7:36   ` Alexandre Courbot
2026-06-29  7:56     ` Alistair Popple [this message]
2026-06-29  9:21     ` Miguel Ojeda
2026-06-29  9:45       ` Alexandre Courbot
2026-06-29  5:55 ` [PATCH 0/1] nova-core: Convert bindings to use zerocopy SeungJong Ha
2026-06-29  7:09   ` Alexandre Courbot
2026-06-29  8:05     ` Alistair Popple
2026-06-29  8:46     ` Danilo Krummrich

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=akIiunspnSSbGWoZ@nvdebian.thelocal \
    --to=apopple@nvidia.com \
    --cc=acourbot@nvidia.com \
    --cc=airlied@gmail.com \
    --cc=aliceryhl@google.com \
    --cc=dakr@kernel.org \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=engineer.jjhama@gmail.com \
    --cc=gary@garyguo.net \
    --cc=linux-kernel@vger.kernel.org \
    --cc=nico.antinori.7@gmail.com \
    --cc=niyudi.honda@usp.br \
    --cc=nova-gpu@lists.linux.de \
    --cc=ojeda@kernel.org \
    --cc=rust-for-linux@vger.kernel.org \
    --cc=simona@ffwll.ch \
    --cc=skhan@linuxfoundation.org \
    --cc=tamird@kernel.org \
    --cc=tmgross@umich.edu \
    --cc=work@onurozkan.dev \
    /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.