From: "Alexandre Courbot" <acourbot@nvidia.com>
To: "Eliot Courtney" <ecourtney@nvidia.com>
Cc: "Danilo Krummrich" <dakr@kernel.org>,
"Lorenzo Stoakes" <ljs@kernel.org>,
"Vlastimil Babka" <vbabka@kernel.org>,
"Liam R. Howlett" <liam@infradead.org>,
"Uladzislau Rezki" <urezki@gmail.com>,
"Miguel Ojeda" <ojeda@kernel.org>,
"Boqun Feng" <boqun@kernel.org>, "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>,
"Daniel Almeida" <daniel.almeida@collabora.com>,
"Tamir Duberstein" <tamird@kernel.org>,
"Onur Özkan" <work@onurozkan.dev>,
"David Airlie" <airlied@gmail.com>,
"Simona Vetter" <simona@ffwll.ch>,
"John Hubbard" <jhubbard@nvidia.com>,
"Alistair Popple" <apopple@nvidia.com>,
"Timur Tabi" <ttabi@nvidia.com>,
rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org,
nova-gpu@lists.linux.dev, dri-devel@lists.freedesktop.org
Subject: Re: [PATCH v3 8/8] gpu: nova-core: add NVKV GSP_INIT schemas
Date: Wed, 07 Oct 2026 19:53:44 +0900 [thread overview]
Message-ID: <DLYJTG5QTTLF.1LPXNI4K9UU87@nvidia.com> (raw)
In-Reply-To: <20260928-b4-nvkv-v3-8-f04504c262c2@nvidia.com>
On Mon Sep 28, 2026 at 5:42 PM JST, Eliot Courtney wrote:
> Add the first user of NVKV encode/decode which is the request and
> response for GSP init. For now this is exercised via unit tests. Later
> patches will support GMCAPI in `Cmdq` and use these messages.
>
> Signed-off-by: Eliot Courtney <ecourtney@nvidia.com>
> ---
> drivers/gpu/nova-core/gsp/fw/commands.rs | 447 ++++++++++++++++++++++++++++++-
> drivers/gpu/nova-core/gsp/nvkv.rs | 3 -
> drivers/gpu/nova-core/gsp/nvkv/decode.rs | 1 +
> drivers/gpu/nova-core/gsp/nvkv/encode.rs | 1 +
> 4 files changed, 448 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/gpu/nova-core/gsp/fw/commands.rs b/drivers/gpu/nova-core/gsp/fw/commands.rs
> index 32856ff74183..02de225af917 100644
> --- a/drivers/gpu/nova-core/gsp/fw/commands.rs
> +++ b/drivers/gpu/nova-core/gsp/fw/commands.rs
> @@ -4,6 +4,8 @@
> use core::ops::Range;
>
> use kernel::{
> + alloc::ArrayVec,
> + bitfield,
> device,
> pci,
> prelude::*,
> @@ -15,7 +17,21 @@
>
> use crate::{
> gpu::Chipset,
> - gsp::GSP_PAGE_SIZE,
> + gsp::{
> + nvkv::{
> + nvkv_decode,
> + nvkv_encode,
> + Accumulated,
> + Array,
> + DecoderValue,
> + Encodable,
> + Encoder,
> + Key,
> + KeyId,
> + Required, //
> + },
> + GSP_PAGE_SIZE, //
> + },
> num::IntoSafeCast, //
> };
>
> @@ -230,3 +246,432 @@ unsafe impl AsBytes for UnloadingGuestDriver {}
> // SAFETY: This struct only contains integer types for which all bit patterns
> // are valid.
> unsafe impl FromBytes for UnloadingGuestDriver {}
> +
> +/// The host CPU architecture.
> +#[derive(Clone, Copy)]
> +pub(crate) enum HostArch {
> + None = 0,
> + X86_64 = 1,
> + Ppc64le = 2,
> + Arm = 3,
> + Aarch64 = 4,
> + Riscv64 = 5,
> +}
> +
> +// TODO[FPRI]: This is a temporary solution to be replaced with the corresponding derive macros once
> +// they land.
> +impl TryFrom<u32> for HostArch {
> + type Error = Error;
> +
> + fn try_from(value: u32) -> Result<Self> {
> + match value {
> + 0 => Ok(Self::None),
> + 1 => Ok(Self::X86_64),
> + 2 => Ok(Self::Ppc64le),
> + 3 => Ok(Self::Arm),
> + 4 => Ok(Self::Aarch64),
> + 5 => Ok(Self::Riscv64),
> + _ => Err(EINVAL),
> + }
> + }
> +}
> +
> +impl From<HostArch> for u32 {
> + fn from(value: HostArch) -> Self {
> + value as u32
> + }
> +}
> +
> +nvkv_encode! {
> + /// A GSP registry entry.
> + struct RegKey {
> + key_name: Key<&'static [u8], { Self::REGKEY_NAME_KEY }>,
> + key_value: Key<u32, { Self::REGKEY_VALUE_U32_KEY }>,
> + }
> +}
> +
> +impl RegKey {
> + // Define the Key IDs read/written by GSP.
> + const REGKEY_NAME_KEY: KeyId = 0x3070;
> + const REGKEY_VALUE_U32_KEY: KeyId = 0x3071;
I guess the `REGKEY` prefix is unneeded here since it's the name of the
wrapping type. If we want a common prefix, let's use `KEY`, e.g.
`KEY_NAME`? Although we might not even need these at all - please see my
last comment on this patch.
> +}
> +
> +impl Encodable for KVVec<RegKey> {
> + fn encode(&self, encoder: &mut Encoder) -> Result {
> + for regkey in self {
> + regkey.encode(encoder)?;
> + }
> + Ok(())
> + }
> +}
> +
> +nvkv_encode! {
> + /// SR-IOV virtual function information.
> + struct VfInfo {
> + total_vfs: Key<u32, { Self::VF_TOTAL_VFS_KEY }>,
> + first_vf_offset: Key<u32, { Self::VF_FIRST_VF_OFFSET_KEY }>,
> + flags: Key<u64, { Self::VF_FLAGS_KEY }>,
> + first_bar0_address: Key<u64, { Self::VF_FIRST_BAR0_ADDRESS_KEY }>,
> + first_bar1_address: Key<u64, { Self::VF_FIRST_BAR1_ADDRESS_KEY }>,
> + first_bar2_address: Key<u64, { Self::VF_FIRST_BAR2_ADDRESS_KEY }>,
> + }
> +}
> +
> +impl VfInfo {
> + // Define the Key IDs read/written by GSP.
> + const VF_TOTAL_VFS_KEY: KeyId = 0x0080;
> + const VF_FIRST_VF_OFFSET_KEY: KeyId = 0x0081;
> + const VF_FLAGS_KEY: KeyId = 0x1003;
> + const VF_FIRST_BAR0_ADDRESS_KEY: KeyId = 0x1050;
> + const VF_FIRST_BAR1_ADDRESS_KEY: KeyId = 0x1051;
> + const VF_FIRST_BAR2_ADDRESS_KEY: KeyId = 0x1052;
> +}
That's a bit of boilerplate. Ideally we would have this `#[nvkv(key =
value)]` notation (without the bidirectional feature) you mentioned in
[1] that takes the literal value and defines a constant to access it,
but I guess that's more rework than we want for now.
[1] https://lore.kernel.org/DLIHSKKUVP7V.153Z4TTEYFL3Y@nvidia.com
> +
> +nvkv_encode! {
> + /// Payload of the `GSP_INIT` command.
> + // TODO: expect() doesn't work here due to Self:: reference, fixed in 1.97.0
> + // https://github.com/rust-lang/rust/pull/154377
> + #[cfg_attr(not(CONFIG_KUNIT), allow(dead_code))]
> + struct GspInitRequest {
> + pci_device_id: Key<u32, { Self::PCI_DEVICE_ID_KEY }>,
> + pci_sub_device_id: Key<u32, { Self::PCI_SUBDEVICE_ID_KEY }>,
> + pci_revision_id: Key<u32, { Self::PCI_REVISION_ID_KEY }>,
> + pci_config_mirror_base: Key<u32, { Self::PCI_CONFIG_MIRROR_BASE_KEY }>,
> + pci_config_mirror_size: Key<u32, { Self::PCI_CONFIG_MIRROR_SIZE_KEY }>,
> + host_arch: Key<HostArch, { Self::HOST_ARCH_KEY }, u32>,
> + bus_device_func: Key<u64, { Self::NV_DOMAIN_BUS_DEVICE_FUNC_KEY }>,
> + regkeys: KVVec<RegKey>,
> + vf_info: Option<VfInfo>,
> + }
> +}
> +
> +impl GspInitRequest {
> + // Define the Key IDs read/written by GSP.
> + const PCI_DEVICE_ID_KEY: KeyId = 0x0001;
> + const PCI_SUBDEVICE_ID_KEY: KeyId = 0x0002;
> + const PCI_REVISION_ID_KEY: KeyId = 0x0003;
> + const PCI_CONFIG_MIRROR_BASE_KEY: KeyId = 0x0010;
> + const PCI_CONFIG_MIRROR_SIZE_KEY: KeyId = 0x0011;
> + const HOST_ARCH_KEY: KeyId = 0x0070;
> + const NV_DOMAIN_BUS_DEVICE_FUNC_KEY: KeyId = 0x1020;
> +}
> +
> +// Decode:
> +
> +// Should decode with UnknownKeyPolicy::Ignore.
> +nvkv_decode! {
> + /// Schema for the `GSP_INIT` response.
> + // TODO: expect() doesn't work here due to Self:: reference, fixed in 1.97.0
> + // https://github.com/rust-lang/rust/pull/154377
> + #[cfg_attr(not(CONFIG_KUNIT), allow(dead_code))]
> + struct GspInitResponseSchema => GspInitResponse {
> + gpu_name:
> + Array<u8, { GspInitResponse::MAX_GPU_NAME_LEN }, { Self::GPU_NAME_STRING_KEY }>,
> + fb_regions: Accumulated<FbRegionSchema>,
> + bar1_pde_base: Required<u64, { Self::BAR1_PDE_BASE_KEY }>,
> + vmmu_segment_size: Key<u64, { Self::VMMU_SEGMENT_SIZE_KEY }>,
Is this ok to have `vmmu_segment_size` not `Required`?
> + }
> +}
> +
> +impl GspInitResponseSchema {
> + // Define the Key IDs read/written by GSP.
> + const GPU_NAME_STRING_KEY: KeyId = 0x2000;
> + const BAR1_PDE_BASE_KEY: KeyId = 0x1020;
> + const VMMU_SEGMENT_SIZE_KEY: KeyId = 0x1050;
> +}
> +
> +/// Payload of the `GSP_INIT` response.
> +struct GspInitResponse {
> + gpu_name: ArrayVec<u8, { Self::MAX_GPU_NAME_LEN }>,
> + fb_regions: KVVec<FbRegion>,
> + bar1_pde_base: u64,
> + vmmu_segment_size: u64,
> +}
> +
> +impl GspInitResponse {
> + const MAX_GPU_NAME_LEN: usize = 64;
> +}
> +
> +nvkv_decode! {
> + /// Schema for one FB region of the `GSP_INIT` response.
> + struct FbRegionSchema => FbRegion {
> + base: Required<u64, { Self::BASE_KEY }>,
> + limit: Required<u64, { Self::LIMIT_KEY }>,
> + flags: Required<FbRegionFlags, { Self::FLAGS_KEY }>,
> + tag: Required<u32, { Self::TAG_KEY }>,
> + }
> +}
> +
> +impl FbRegionSchema {
> + // Define the Key IDs read/written by GSP.
> + const BASE_KEY: KeyId = 0x1011;
> + const LIMIT_KEY: KeyId = 0x1012;
> + const FLAGS_KEY: KeyId = 0x0012;
> + const TAG_KEY: KeyId = 0x0013;
> +}
> +
> +bitfield! {
> + /// FB region attribute flags.
> + struct FbRegionFlags(u32) {
> + 0:0 support_compressed => bool;
> + 1:1 support_iso => bool;
> + 2:2 protected => bool;
> + }
> +}
> +
> +impl TryFrom<DecoderValue<'_>> for FbRegionFlags {
> + type Error = Error;
> +
> + fn try_from(value: DecoderValue<'_>) -> Result<Self> {
> + if let DecoderValue::Scalar32(v) = value {
> + Ok(v.into())
> + } else {
> + Err(EINVAL)
> + }
> + }
> +}
> +
> +/// One FB memory region.
> +struct FbRegion {
> + base: u64,
> + limit: u64,
> + flags: FbRegionFlags,
> + tag: u32,
> +}
> +
> +#[kunit_tests(nova_core_fw_commands)]
> +mod tests {
These tests below mostly re-check the same things as the previous
patches, only with different data. I am not sure they bring much new
coverage, except maybe nested structs (which we could/should also cover
in the previous patches anyway). I think we would have more value (and
less code) if we covered the things newly tested to the tests of patches
4-7, and dropped the test module here altogether. Because if we follow
the pattern, then we will repeat these tests again and again for every
command we support, which is going to result in tons of redundant tests
at the end of the day.
Another incentive for not having more tests here: they are the only
other user of the key constants, outside of the `nvkv_decode` and
`nvkv_encode` macros themselves. If we can get rid of them then the
macros become the only users of these consts, and in that case why not
replace
pci_device_id: Key<u32, { Self::PCI_DEVICE_ID_KEY }>,
...
const PCI_DEVICE_ID_KEY: KeyId = 0x0001;
with just
pci_device_id: Key<u32, 0x0001>,
as it is clear from that line alone that `0x0001` is the key for
`pci_device_id`. Bonus, the unsightly brackets required because we
reference `Self` can also go away.
prev parent reply other threads:[~2026-10-07 10:53 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-28 8:42 [PATCH v3 0/8] gpu: nova-core: add NVKV codec Eliot Courtney
2026-09-28 8:42 ` [PATCH v3 1/8] rust: alloc: add Vec::try_push_init Eliot Courtney
2026-10-06 5:52 ` Alexandre Courbot
2026-09-28 8:42 ` [PATCH v3 2/8] rust: alloc: add Vec::push_init Eliot Courtney
2026-10-06 6:10 ` Alexandre Courbot
2026-09-28 8:42 ` [PATCH v3 3/8] rust: alloc: add ArrayVec Eliot Courtney
2026-10-07 6:27 ` Alexandre Courbot
2026-09-28 8:42 ` [PATCH v3 4/8] gpu: nova-core: add NVKV encoder Eliot Courtney
2026-10-07 3:43 ` Alexandre Courbot
2026-10-07 3:48 ` Alexandre Courbot
2026-10-07 11:33 ` John Hubbard
2026-10-07 11:56 ` Alexandre Courbot
2026-09-28 8:42 ` [PATCH v3 5/8] gpu: nova-core: add NVKV decoder Eliot Courtney
2026-10-07 4:51 ` Alexandre Courbot
2026-09-28 8:42 ` [PATCH v3 6/8] gpu: nova-core: add NVKV typed encoding Eliot Courtney
2026-10-07 6:30 ` Alexandre Courbot
2026-09-28 8:42 ` [PATCH v3 7/8] gpu: nova-core: add NVKV typed decoding Eliot Courtney
2026-10-07 6:30 ` Alexandre Courbot
2026-10-07 12:05 ` Alexandre Courbot
2026-09-28 8:42 ` [PATCH v3 8/8] gpu: nova-core: add NVKV GSP_INIT schemas Eliot Courtney
2026-10-07 10:53 ` Alexandre Courbot [this message]
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=DLYJTG5QTTLF.1LPXNI4K9UU87@nvidia.com \
--to=acourbot@nvidia.com \
--cc=a.hindborg@kernel.org \
--cc=airlied@gmail.com \
--cc=aliceryhl@google.com \
--cc=apopple@nvidia.com \
--cc=bjorn3_gh@protonmail.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=gary@garyguo.net \
--cc=jhubbard@nvidia.com \
--cc=liam@infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=ljs@kernel.org \
--cc=lossin@kernel.org \
--cc=nova-gpu@lists.linux.dev \
--cc=ojeda@kernel.org \
--cc=rust-for-linux@vger.kernel.org \
--cc=simona@ffwll.ch \
--cc=tamird@kernel.org \
--cc=tmgross@umich.edu \
--cc=ttabi@nvidia.com \
--cc=urezki@gmail.com \
--cc=vbabka@kernel.org \
--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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®