From: John Hubbard <jhubbard@nvidia.com>
To: Danilo Krummrich <dakr@kernel.org>,
Alexandre Courbot <acourbot@nvidia.com>
Cc: "Timur Tabi" <ttabi@nvidia.com>,
"Alistair Popple" <apopple@nvidia.com>,
"Eliot Courtney" <ecourtney@nvidia.com>,
"Zhi Wang" <zhiw@nvidia.com>, "David Airlie" <airlied@gmail.com>,
"Simona Vetter" <simona@ffwll.ch>,
"Bjorn Helgaas" <bhelgaas@google.com>,
"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" <lossin@kernel.org>,
"Andreas Hindborg" <a.hindborg@kernel.org>,
"Alice Ryhl" <aliceryhl@google.com>,
"Trevor Gross" <tmgross@umich.edu>,
nova-gpu@lists.linux.dev, LKML <linux-kernel@vger.kernel.org>,
"John Hubbard" <jhubbard@nvidia.com>
Subject: [PATCH 22/27] gpu: nova-core: gsp: add the GSP_INIT request builder
Date: Tue, 18 Aug 2026 20:52:15 -0700 [thread overview]
Message-ID: <20260819035221.336390-23-jhubbard@nvidia.com> (raw)
In-Reply-To: <20260819035221.336390-1-jhubbard@nvidia.com>
The r000 GSP boot protocol replaces the separate system-info, registry
and static-info commands with one GSP_INIT request, whose payload is an
NVKV key-value blob rather than a packed struct.
Nova-core has the NVKV codec and the GSP_INIT schema, but nothing that
fills the schema in from a PCI device.
Add the builder. It encodes the PCI identifiers and config mirror range
the RPC path already sends, and the registry entries, whose names carry
the NULL that GSP-RM counts in the encoded length.
Assisted-by: Cursor:claude-opus-5
Signed-off-by: John Hubbard <jhubbard@nvidia.com>
---
drivers/gpu/nova-core/gsp/commands.rs | 52 +++++++++++++++++++++
drivers/gpu/nova-core/gsp/fw/commands.rs | 58 +++++++++++++++++++++++-
2 files changed, 108 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/nova-core/gsp/commands.rs b/drivers/gpu/nova-core/gsp/commands.rs
index d5575c036eb9..0c3832ccf726 100644
--- a/drivers/gpu/nova-core/gsp/commands.rs
+++ b/drivers/gpu/nova-core/gsp/commands.rs
@@ -30,8 +30,16 @@
},
fw::{
self,
+ commands::{
+ GspInitRequest,
+ RegKey, //
+ },
MsgFunction, //
},
+ nvkv::{
+ Encodeable,
+ Encoder, //
+ },
},
sbuffer::SBufferIter,
vgpu::VgpuState, //
@@ -259,6 +267,50 @@ pub(crate) fn gpu_name(&self) -> core::result::Result<&str, GpuNameError> {
}
}
+/// Registry entries the driver sends to GSP-RM on every boot, each with the NULL terminator that
+/// Open RM counts in the encoded name length.
+///
+/// `RMSecBusResetEnable` enables PCI secondary bus reset. `RMForcePcieConfigSave` makes GSP-RM
+/// preserve PCI configuration registers across any PCI reset. `RMDevidCheckIgnore` lets GSP-RM
+/// boot when the PCI device id is absent from its product name database.
+///
+/// [`SetRegistry::new`] carries the same entries for the RPC path, where the names have no
+/// terminator because that encoding appends one.
+const REGISTRY_ENTRIES: &[(&[u8], u32)] = &[
+ (b"RMSecBusResetEnable\0", 1),
+ (b"RMForcePcieConfigSave\0", 1),
+ (b"RMDevidCheckIgnore\0", 1),
+];
+
+/// Builds the NVKV-encoded payload of a `GSP_INIT` request.
+///
+/// The payload carries the system information GSP-RM reads before it starts, and
+/// [`REGISTRY_ENTRIES`] as `REGKEY_NAME` and `REGKEY_VALUE_U32` pairs. GSP-RM requires each name
+/// to be followed by its value, which is the order [`RegKey`] declares them in.
+///
+/// # Errors
+///
+/// - `ENOMEM` if the registry list or the encoder buffer cannot be allocated.
+#[expect(dead_code)]
+pub(crate) fn build_gsp_init_payload(
+ pdev: &pci::Device<device::Bound>,
+ chipset: Chipset,
+ vgpu_state: VgpuState,
+) -> Result<KVVec<u64>> {
+ let mut regkeys = KVVec::new();
+ for &(name, value) in REGISTRY_ENTRIES {
+ regkeys.push(RegKey::new(name, value), GFP_KERNEL)?;
+ }
+ if matches!(vgpu_state, VgpuState::Enabled { .. }) {
+ regkeys.push(RegKey::new(b"RMSetSriovMode\0", 1), GFP_KERNEL)?;
+ }
+
+ let mut encoder = Encoder::new();
+ GspInitRequest::new(pdev, chipset, regkeys).encode(&mut encoder)?;
+
+ Ok(encoder.finish())
+}
+
pub(crate) use fw::commands::PowerStateLevel;
/// The `UnloadingGuestDriver` command, used to shut down the GSP.
diff --git a/drivers/gpu/nova-core/gsp/fw/commands.rs b/drivers/gpu/nova-core/gsp/fw/commands.rs
index 5cd2d9646de3..bfd756813c64 100644
--- a/drivers/gpu/nova-core/gsp/fw/commands.rs
+++ b/drivers/gpu/nova-core/gsp/fw/commands.rs
@@ -245,6 +245,25 @@ pub(crate) enum OorArch {
Riscv64 = 5,
}
+impl OorArch {
+ /// Returns the variant naming the architecture this kernel is built for.
+ fn host() -> Self {
+ if cfg!(target_arch = "x86_64") {
+ Self::X86_64
+ } else if cfg!(target_arch = "aarch64") {
+ Self::Aarch64
+ } else if cfg!(target_arch = "powerpc64") {
+ Self::Ppc64le
+ } else if cfg!(target_arch = "arm") {
+ Self::Arm
+ } else if cfg!(target_arch = "riscv64") {
+ Self::Riscv64
+ } else {
+ Self::None
+ }
+ }
+}
+
// TODO[FPRI]: This is a temporary solution to be replaced with the corresponding derive macros once
// they land.
impl TryFrom<u32> for OorArch {
@@ -271,7 +290,7 @@ fn from(value: OorArch) -> Self {
nvkv_encode! {
/// A GSP registry entry.
- struct RegKey {
+ pub(crate) struct RegKey {
key_name: Key<&'static [u8], { Self::REGKEY_NAME_KEY }>,
key_value: Key<u32, { Self::REGKEY_VALUE_U32_KEY }>,
}
@@ -280,6 +299,15 @@ struct RegKey {
impl RegKey {
const REGKEY_NAME_KEY: KeyId = 0x3070;
const REGKEY_VALUE_U32_KEY: KeyId = 0x3071;
+
+ /// Creates a registry entry. `key_name` must include its NULL terminator, which GSP-RM counts
+ /// in the encoded name length.
+ pub(crate) fn new(key_name: &'static [u8], key_value: u32) -> Self {
+ Self {
+ key_name: key_name.into(),
+ key_value: key_value.into(),
+ }
+ }
}
impl Encodeable for KVVec<RegKey> {
@@ -317,7 +345,7 @@ impl VfInfo {
nvkv_encode! {
/// Payload of the `GSP_INIT` command.
#[cfg_attr(not(CONFIG_KUNIT), allow(dead_code))]
- struct GspInitRequest {
+ pub(crate) 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 }>,
@@ -339,6 +367,32 @@ impl GspInitRequest {
const PCI_CONFIG_MIRROR_SIZE_KEY: KeyId = 0x0011;
const OOR_ARCH_KEY: KeyId = 0x0070;
const NV_DOMAIN_BUS_DEVICE_FUNC_KEY: KeyId = 0x1020;
+
+ /// Describes `dev` to GSP-RM and asks it to apply `regkeys`.
+ ///
+ /// The same identifiers reach GSP-RM through [`GspSetSystemInfo::init`] on the RPC path.
+ pub(crate) fn new(
+ dev: &pci::Device<device::Bound>,
+ chipset: Chipset,
+ regkeys: KVVec<RegKey>,
+ ) -> Self {
+ let mirror = chipset.pci_config_mirror_range();
+ let device_id = (u32::from(dev.device_id()) << 16) | u32::from(dev.vendor_id().as_raw());
+ let sub_device_id =
+ (u32::from(dev.subsystem_device_id()) << 16) | u32::from(dev.subsystem_vendor_id());
+
+ Self {
+ pci_device_id: device_id.into(),
+ pci_sub_device_id: sub_device_id.into(),
+ pci_revision_id: u32::from(dev.revision_id()).into(),
+ pci_config_mirror_base: mirror.start.into(),
+ pci_config_mirror_size: (mirror.end - mirror.start).into(),
+ oor_arch: OorArch::host().into(),
+ bus_device_func: u64::from(dev.dev_id()).into(),
+ regkeys,
+ vf_info: None,
+ }
+ }
}
// Decode:
--
2.55.0
next prev parent reply other threads:[~2026-08-19 3:53 UTC|newest]
Thread overview: 28+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-19 3:51 [PATCH 00/27] gpu: nova-core: boot on the r000 GSP firmware John Hubbard
2026-08-19 3:51 ` [PATCH 01/27] gpu: nova-core: firmware: add r000 bindings John Hubbard
2026-08-19 3:51 ` [PATCH 02/27] gpu: nova-core: extract radix3 page table into its own module John Hubbard
2026-08-19 3:51 ` [PATCH 03/27] gpu: nova-core: set MCTP transport header version to 1 John Hubbard
2026-08-19 3:51 ` [PATCH 04/27] gpu: nova-core: add Falcon helpers for r000 LOAD_EXEC events John Hubbard
2026-08-19 3:51 ` [PATCH 05/27] gpu: nova-core: zero-pad radix3 page table levels to page boundary John Hubbard
2026-08-19 3:51 ` [PATCH 06/27] gpu: nova-core: distinguish async GSP RPC traffic in debug logs John Hubbard
2026-08-19 3:52 ` [PATCH 07/27] gpu: nova-core: add optional ucodes firmware loading John Hubbard
2026-08-19 3:52 ` [PATCH 08/27] gpu: nova-core: add LIBOS3 log buffers and state monitor buffer John Hubbard
2026-08-19 3:52 ` [PATCH 09/27] gpu: nova-core: add build ID headers to debugfs log buffer dumps John Hubbard
2026-08-19 3:52 ` [PATCH 10/27] gpu: nova-core: rename the FbRanges elf field to fw_image John Hubbard
2026-08-19 3:52 ` [PATCH 11/27] gpu: nova-core: regs: add msgq v2 BAR0 register declarations John Hubbard
2026-08-19 3:52 ` [PATCH 12/27] gpu: nova-core: gsp: add msgq v2 internals John Hubbard
2026-08-19 3:52 ` [PATCH 13/27] gpu: nova-core: generalize allocate_command() for variable headers John Hubbard
2026-08-19 3:52 ` [PATCH 14/27] gpu: nova-core: add GMC API message types John Hubbard
2026-08-19 3:52 ` [PATCH 15/27] gpu: nova-core: add GMC send path John Hubbard
2026-08-19 3:52 ` [PATCH 16/27] gpu: nova-core: add GMC transport receive path John Hubbard
2026-08-19 3:52 ` [PATCH 17/27] gpu: nova-core: gsp: add GMC dispatch on receive John Hubbard
2026-08-19 3:52 ` [PATCH 18/27] gpu: nova-core: separate the generic falcon bootloader from FWSEC John Hubbard
2026-08-19 3:52 ` [PATCH 19/27] gpu: nova-core: handle the r000 load-and-execute HS binary event John Hubbard
2026-08-19 3:52 ` [PATCH 20/27] gpu: nova-core: handle the r000 load-and-execute bootloader event John Hubbard
2026-08-19 3:52 ` [PATCH 21/27] gpu: nova-core: gsp: add the GMC boot event dispatcher John Hubbard
2026-08-19 3:52 ` John Hubbard [this message]
2026-08-19 3:52 ` [PATCH 23/27] gpu: nova-core: gsp: send GSP_INIT and decode its reply John Hubbard
2026-08-19 3:52 ` [PATCH 24/27] gpu: nova-core: gsp: pass the remaining log buffers to GSP-RM John Hubbard
2026-08-19 3:52 ` [PATCH 25/27] gpu: nova-core: switch to the r000 GSP firmware John Hubbard
2026-08-19 3:52 ` [PATCH 26/27] gpu: nova-core: gsp: remove the retired system-info and static-info RPCs John Hubbard
2026-08-19 3:52 ` [PATCH 27/27] gpu: nova-core: firmware: delete the r570 bindings John Hubbard
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=20260819035221.336390-23-jhubbard@nvidia.com \
--to=jhubbard@nvidia.com \
--cc=a.hindborg@kernel.org \
--cc=acourbot@nvidia.com \
--cc=airlied@gmail.com \
--cc=alex.gaynor@gmail.com \
--cc=aliceryhl@google.com \
--cc=apopple@nvidia.com \
--cc=bhelgaas@google.com \
--cc=bjorn3_gh@protonmail.com \
--cc=boqun.feng@gmail.com \
--cc=dakr@kernel.org \
--cc=ecourtney@nvidia.com \
--cc=gary@garyguo.net \
--cc=linux-kernel@vger.kernel.org \
--cc=lossin@kernel.org \
--cc=nova-gpu@lists.linux.dev \
--cc=ojeda@kernel.org \
--cc=simona@ffwll.ch \
--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