From: John Hubbard <jhubbard@nvidia.com>
To: Danilo Krummrich <dakr@kernel.org>,
Alexandre Courbot <acourbot@nvidia.com>
Cc: "Joel Fernandes" <joelagnelf@nvidia.com>,
"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>,
nouveau@lists.freedesktop.org, rust-for-linux@vger.kernel.org,
LKML <linux-kernel@vger.kernel.org>,
"John Hubbard" <jhubbard@nvidia.com>
Subject: [PATCH v5 36/38] gpu: nova-core: Hopper/Blackwell: integrate FSP boot path into boot()
Date: Fri, 20 Feb 2026 18:09:50 -0800 [thread overview]
Message-ID: <20260221020952.412352-37-jhubbard@nvidia.com> (raw)
In-Reply-To: <20260221020952.412352-1-jhubbard@nvidia.com>
Add the FSP boot path for Hopper and Blackwell GPUs. These architectures
use FSP with FMC firmware for Chain of Trust boot, rather than SEC2.
boot() now dispatches to boot_via_sec2() or boot_via_fsp() based on
architecture. The SEC2 path keeps its original command ordering. The
FSP path sends SetSystemInfo/SetRegistry after GSP becomes active.
The GSP sequencer only runs for SEC2-based architectures.
Signed-off-by: John Hubbard <jhubbard@nvidia.com>
---
drivers/gpu/nova-core/firmware/fsp.rs | 2 -
drivers/gpu/nova-core/fsp.rs | 5 -
drivers/gpu/nova-core/gsp/boot.rs | 190 +++++++++++++++++++-------
3 files changed, 144 insertions(+), 53 deletions(-)
diff --git a/drivers/gpu/nova-core/firmware/fsp.rs b/drivers/gpu/nova-core/firmware/fsp.rs
index bb35f363b998..0e72f1378ef0 100644
--- a/drivers/gpu/nova-core/firmware/fsp.rs
+++ b/drivers/gpu/nova-core/firmware/fsp.rs
@@ -13,7 +13,6 @@
gpu::Chipset, //
};
-#[expect(dead_code)]
pub(crate) struct FspFirmware {
/// FMC firmware image data (only the "image" ELF section).
pub(crate) fmc_image: DmaObject,
@@ -22,7 +21,6 @@ pub(crate) struct FspFirmware {
}
impl FspFirmware {
- #[expect(dead_code)]
pub(crate) fn new(
dev: &device::Device<device::Bound>,
chipset: Chipset,
diff --git a/drivers/gpu/nova-core/fsp.rs b/drivers/gpu/nova-core/fsp.rs
index c66ad0a102a6..3749b5e3a677 100644
--- a/drivers/gpu/nova-core/fsp.rs
+++ b/drivers/gpu/nova-core/fsp.rs
@@ -238,7 +238,6 @@ pub(crate) struct FmcBootArgs<'a> {
impl<'a> FmcBootArgs<'a> {
/// Build FMC boot arguments, allocating the DMA-coherent boot parameter
/// structure that FSP will read.
- #[expect(dead_code)]
#[allow(clippy::too_many_arguments)]
pub(crate) fn new(
dev: &device::Device<device::Bound>,
@@ -287,7 +286,6 @@ pub(crate) fn new(
/// DMA address of the FMC boot parameters, needed after boot for lockdown
/// release polling.
- #[expect(dead_code)]
pub(crate) fn boot_params_dma_handle(&self) -> u64 {
self.fmc_boot_params.dma_handle()
}
@@ -301,7 +299,6 @@ impl Fsp {
///
/// Polls the thermal scratch register until FSP signals boot completion
/// or timeout occurs.
- #[expect(dead_code)]
pub(crate) fn wait_secure_boot(
dev: &device::Device<device::Bound>,
bar: &crate::driver::Bar0,
@@ -331,7 +328,6 @@ pub(crate) fn wait_secure_boot(
///
/// Extracts real cryptographic signatures from FMC ELF32 firmware sections.
/// Returns signatures in a heap-allocated structure to prevent stack overflow.
- #[expect(dead_code)]
pub(crate) fn extract_fmc_signatures(
dev: &device::Device<device::Bound>,
fmc_fw_data: &[u8],
@@ -391,7 +387,6 @@ pub(crate) fn extract_fmc_signatures(
///
/// Builds the COT message from the pre-configured [`FmcBootArgs`], sends it
/// to FSP, and waits for the response.
- #[expect(dead_code)]
pub(crate) fn boot_fmc(
dev: &device::Device<device::Bound>,
bar: &crate::driver::Bar0,
diff --git a/drivers/gpu/nova-core/gsp/boot.rs b/drivers/gpu/nova-core/gsp/boot.rs
index 0db2c58e0765..1fdcb72ce163 100644
--- a/drivers/gpu/nova-core/gsp/boot.rs
+++ b/drivers/gpu/nova-core/gsp/boot.rs
@@ -13,6 +13,7 @@
use crate::{
driver::Bar0,
falcon::{
+ fsp::Fsp as FspEngine,
gsp::Gsp,
sec2::Sec2,
Falcon,
@@ -24,6 +25,7 @@
BooterFirmware,
BooterKind, //
},
+ fsp::FspFirmware,
fwsec::{
FwsecCommand,
FwsecFirmware, //
@@ -31,9 +33,17 @@
gsp::GspFirmware,
FIRMWARE_VERSION, //
},
- gpu::Chipset,
+ fsp::{
+ FmcBootArgs,
+ Fsp, //
+ },
+ gpu::{
+ Architecture,
+ Chipset, //
+ },
gsp::{
commands,
+ fw::LibosMemoryRegionInitArgument,
sequencer::{
GspSequencer,
GspSequencerParams, //
@@ -188,8 +198,83 @@ fn run_booter(
booter.run(dev, bar, sec2_falcon, wpr_meta)
}
+ /// Boot GSP via SEC2 booter firmware (Turing/Ampere/Ada path).
+ ///
+ /// This path uses FWSEC-FRTS to set up WPR2, then boots GSP directly,
+ /// then uses SEC2 to run the booter firmware.
+ #[allow(clippy::too_many_arguments)]
+ fn boot_via_sec2(
+ dev: &device::Device<device::Bound>,
+ bar: &Bar0,
+ chipset: Chipset,
+ gsp_falcon: &Falcon<Gsp>,
+ sec2_falcon: &Falcon<Sec2>,
+ fb_layout: &FbLayout,
+ libos: &CoherentAllocation<LibosMemoryRegionInitArgument>,
+ wpr_meta: &CoherentAllocation<GspFwWprMeta>,
+ ) -> Result {
+ // Run FWSEC-FRTS to set up the WPR2 region
+ let bios = Vbios::new(dev, bar)?;
+ Self::run_fwsec_frts(dev, gsp_falcon, bar, &bios, fb_layout)?;
+
+ // Reset and boot GSP before SEC2
+ gsp_falcon.reset(bar)?;
+ let libos_handle = libos.dma_handle();
+ let (mbox0, mbox1) = gsp_falcon.boot(
+ bar,
+ Some(libos_handle as u32),
+ Some((libos_handle >> 32) as u32),
+ )?;
+ dev_dbg!(dev, "GSP MBOX0: {:#x}, MBOX1: {:#x}\n", mbox0, mbox1);
+ dev_dbg!(
+ dev,
+ "Using SEC2 to load and run the booter_load firmware...\n"
+ );
+
+ // Run booter via SEC2
+ Self::run_booter(dev, bar, chipset, sec2_falcon, wpr_meta)
+ }
+
+ /// Boot GSP via FSP Chain of Trust (Hopper/Blackwell+ path).
+ ///
+ /// This path uses FSP to establish a chain of trust and boot GSP-FMC. FSP handles
+ /// the GSP boot internally - no manual GSP reset/boot is needed.
+ fn boot_via_fsp(
+ dev: &device::Device<device::Bound>,
+ bar: &Bar0,
+ chipset: Chipset,
+ gsp_falcon: &Falcon<Gsp>,
+ wpr_meta: &CoherentAllocation<GspFwWprMeta>,
+ libos: &CoherentAllocation<LibosMemoryRegionInitArgument>,
+ ) -> Result {
+ let fsp_falcon = Falcon::<FspEngine>::new(dev, chipset)?;
+
+ Fsp::wait_secure_boot(dev, bar, chipset.arch())?;
+
+ let fsp_fw = FspFirmware::new(dev, chipset, FIRMWARE_VERSION)?;
+
+ let signatures = Fsp::extract_fmc_signatures(dev, &fsp_fw.fmc_full)?;
+
+ let args = FmcBootArgs::new(
+ dev,
+ chipset,
+ &fsp_fw.fmc_image,
+ wpr_meta.dma_handle(),
+ core::mem::size_of::<GspFwWprMeta>() as u32,
+ libos.dma_handle(),
+ false,
+ &signatures,
+ )?;
+
+ Fsp::boot_fmc(dev, bar, &fsp_falcon, &args)?;
+
+ let fmc_boot_params_addr = args.boot_params_dma_handle();
+ Self::wait_for_gsp_lockdown_release(dev, bar, gsp_falcon, fmc_boot_params_addr)?;
+
+ Ok(())
+ }
+
/// Wait for GSP lockdown to be released after FSP Chain of Trust.
- #[expect(dead_code)]
fn wait_for_gsp_lockdown_release(
dev: &device::Device<device::Bound>,
bar: &Bar0,
@@ -233,45 +318,49 @@ pub(crate) fn boot(
sec2_falcon: &Falcon<Sec2>,
) -> Result {
let dev = pdev.as_ref();
-
- let bios = Vbios::new(dev, bar)?;
+ let uses_sec2 = matches!(
+ chipset.arch(),
+ Architecture::Turing | Architecture::Ampere | Architecture::Ada
+ );
let gsp_fw = KBox::pin_init(GspFirmware::new(dev, chipset, FIRMWARE_VERSION), GFP_KERNEL)?;
let fb_layout = FbLayout::new(chipset, bar, &gsp_fw)?;
dev_dbg!(dev, "{:#x?}\n", fb_layout);
- Self::run_fwsec_frts(dev, gsp_falcon, bar, &bios, &fb_layout)?;
-
let wpr_meta =
CoherentAllocation::<GspFwWprMeta>::alloc_coherent(dev, 1, GFP_KERNEL | __GFP_ZERO)?;
dma_write!(wpr_meta[0] = GspFwWprMeta::new(&gsp_fw, &fb_layout))?;
- self.cmdq
- .send_command(bar, commands::SetSystemInfo::new(pdev, chipset))?;
- self.cmdq.send_command(bar, commands::SetRegistry::new())?;
-
- gsp_falcon.reset(bar)?;
- let libos_handle = self.libos.dma_handle();
- let (mbox0, mbox1) = gsp_falcon.boot(
- bar,
- Some(libos_handle as u32),
- Some((libos_handle >> 32) as u32),
- )?;
- dev_dbg!(
- pdev,
- "GSP MBOX0: {:#x}, MBOX1: {:#x}\n",
- mbox0,
- mbox1
- );
-
- dev_dbg!(
- pdev,
- "Using SEC2 to load and run the booter_load firmware...\n"
- );
+ // Architecture-specific boot path
+ if uses_sec2 {
+ // SEC2 path: send commands before GSP reset/boot (original order).
+ self.cmdq
+ .send_command(bar, commands::SetSystemInfo::new(pdev, chipset))?;
+ self.cmdq.send_command(bar, commands::SetRegistry::new())?;
- Self::run_booter(dev, bar, chipset, sec2_falcon, &wpr_meta)?;
+ Self::boot_via_sec2(
+ dev,
+ bar,
+ chipset,
+ gsp_falcon,
+ sec2_falcon,
+ &fb_layout,
+ &self.libos,
+ &wpr_meta,
+ )?;
+ } else {
+ Self::boot_via_fsp(
+ dev,
+ bar,
+ chipset,
+ gsp_falcon,
+ &wpr_meta,
+ &self.libos,
+ )?;
+ }
+ // Common post-boot initialization
gsp_falcon.write_os_version(bar, gsp_fw.bootloader.app_version);
// Poll for RISC-V to become active before running sequencer
@@ -282,22 +371,31 @@ pub(crate) fn boot(
Delta::from_secs(5),
)?;
- dev_dbg!(
- pdev,
- "RISC-V active? {}\n",
- gsp_falcon.is_riscv_active(bar),
- );
+ dev_dbg!(dev, "RISC-V active? {}\n", gsp_falcon.is_riscv_active(bar));
- // Create and run the GSP sequencer.
- let seq_params = GspSequencerParams {
- bootloader_app_version: gsp_fw.bootloader.app_version,
- libos_dma_handle: libos_handle,
- gsp_falcon,
- sec2_falcon,
- dev: pdev.as_ref().into(),
- bar,
- };
- GspSequencer::run(&mut self.cmdq, seq_params)?;
+ // For FSP path, send commands after GSP becomes active.
+ if matches!(
+ chipset.arch(),
+ Architecture::Hopper | Architecture::Blackwell
+ ) {
+ self.cmdq
+ .send_command(bar, commands::SetSystemInfo::new(pdev, chipset))?;
+ self.cmdq.send_command(bar, commands::SetRegistry::new())?;
+ }
+
+ // SEC2-based architectures need to run the GSP sequencer
+ if uses_sec2 {
+ let libos_handle = self.libos.dma_handle();
+ let seq_params = GspSequencerParams {
+ bootloader_app_version: gsp_fw.bootloader.app_version,
+ libos_dma_handle: libos_handle,
+ gsp_falcon,
+ sec2_falcon,
+ dev: dev.into(),
+ bar,
+ };
+ GspSequencer::run(&mut self.cmdq, seq_params)?;
+ }
// Wait until GSP is fully initialized.
commands::wait_gsp_init_done(&mut self.cmdq)?;
@@ -305,8 +403,8 @@ pub(crate) fn boot(
// Obtain and display basic GPU information.
let info = commands::get_gsp_info(&mut self.cmdq, bar)?;
match info.gpu_name() {
- Ok(name) => dev_info!(pdev, "GPU name: {}\n", name),
- Err(e) => dev_warn!(pdev, "GPU name unavailable: {:?}\n", e),
+ Ok(name) => dev_info!(dev, "GPU name: {}\n", name),
+ Err(e) => dev_warn!(dev, "GPU name unavailable: {:?}\n", e),
}
Ok(())
--
2.53.0
next prev parent reply other threads:[~2026-02-21 2:11 UTC|newest]
Thread overview: 68+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-02-21 2:09 [PATCH v5 00/38] gpu: nova-core: firmware: Hopper/Blackwell support John Hubbard
2026-02-21 2:09 ` [PATCH v5 01/38] gpu: nova-core: fix aux device registration for multi-GPU systems John Hubbard
2026-02-24 14:47 ` Danilo Krummrich
2026-02-27 15:37 ` Gary Guo
2026-02-27 15:41 ` Gary Guo
2026-02-27 16:05 ` Danilo Krummrich
2026-02-27 16:29 ` John Hubbard
2026-02-21 2:09 ` [PATCH v5 02/38] gpu: nova-core: pass pdev directly to dev_* logging macros John Hubbard
2026-02-21 2:09 ` [PATCH v5 03/38] gpu: nova-core: print FB sizes, along with ranges John Hubbard
2026-02-21 2:09 ` [PATCH v5 04/38] gpu: nova-core: add FbRange.len() and use it in boot.rs John Hubbard
2026-02-21 2:09 ` [PATCH v5 05/38] gpu: nova-core: Hopper/Blackwell: basic GPU identification John Hubbard
2026-02-21 2:09 ` [PATCH v5 06/38] gpu: nova-core: factor .fwsignature* selection into a new find_gsp_sigs_section() John Hubbard
2026-02-21 2:09 ` [PATCH v5 07/38] gpu: nova-core: use GPU Architecture to simplify HAL selections John Hubbard
2026-02-21 2:09 ` [PATCH v5 08/38] gpu: nova-core: apply the one "use" item per line policy to commands.rs John Hubbard
2026-02-21 2:09 ` [PATCH v5 09/38] gpu: nova-core: move GPU init and DMA mask setup into Gpu::new() John Hubbard
2026-02-21 2:09 ` [PATCH v5 10/38] gpu: nova-core: set DMA mask width based on GPU architecture John Hubbard
2026-02-21 2:09 ` [PATCH v5 11/38] gpu: nova-core: Hopper/Blackwell: skip GFW boot waiting John Hubbard
2026-02-21 2:09 ` [PATCH v5 12/38] gpu: nova-core: move firmware image parsing code to firmware.rs John Hubbard
2026-02-21 2:09 ` [PATCH v5 13/38] gpu: nova-core: factor out an elf_str() function John Hubbard
2026-02-21 2:09 ` [PATCH v5 14/38] gpu: nova-core: don't assume 64-bit firmware images John Hubbard
2026-02-21 2:09 ` [PATCH v5 15/38] gpu: nova-core: add support for 32-bit " John Hubbard
2026-02-21 2:09 ` [PATCH v5 16/38] gpu: nova-core: add auto-detection of 32-bit, 64-bit " John Hubbard
2026-02-21 2:09 ` [PATCH v5 17/38] gpu: nova-core: Hopper/Blackwell: add FMC firmware image, in support of FSP John Hubbard
2026-02-21 2:09 ` [PATCH v5 18/38] gpu: nova-core: Hopper/Blackwell: add FSP falcon engine stub John Hubbard
2026-02-21 2:09 ` [PATCH v5 19/38] gpu: nova-core: Hopper/Blackwell: add FSP falcon EMEM operations John Hubbard
2026-02-21 2:09 ` [PATCH v5 20/38] gpu: nova-core: Hopper/Blackwell: add FSP message infrastructure John Hubbard
2026-02-21 2:09 ` [PATCH v5 21/38] rust: ptr: add const_align_up() and enable inline_const feature John Hubbard
2026-02-21 20:50 ` Miguel Ojeda
2026-02-22 19:03 ` John Hubbard
2026-02-22 19:08 ` Miguel Ojeda
2026-02-23 3:36 ` Alexandre Courbot
2026-02-22 7:46 ` Gary Guo
2026-02-22 19:04 ` John Hubbard
2026-02-23 11:07 ` Danilo Krummrich
2026-02-23 14:16 ` Gary Guo
2026-02-23 14:20 ` Danilo Krummrich
2026-03-04 3:47 ` John Hubbard
2026-03-04 11:18 ` Gary Guo
2026-03-04 18:53 ` John Hubbard
2026-03-04 19:04 ` Gary Guo
2026-03-04 19:14 ` John Hubbard
2026-03-05 1:23 ` Alexandre Courbot
2026-03-05 1:31 ` John Hubbard
2026-03-05 7:07 ` Alexandre Courbot
2026-03-05 12:28 ` Gary Guo
2026-03-05 12:36 ` Danilo Krummrich
2026-03-05 12:59 ` Gary Guo
2026-03-05 13:59 ` Alexandre Courbot
2026-03-05 14:05 ` Gary Guo
2026-03-05 15:17 ` Alexandre Courbot
2026-02-23 11:23 ` Alice Ryhl
2026-02-21 2:09 ` [PATCH v5 22/38] gpu: nova-core: Hopper/Blackwell: calculate reserved FB heap size John Hubbard
2026-02-21 2:09 ` [PATCH v5 23/38] gpu: nova-core: add MCTP/NVDM protocol types for firmware communication John Hubbard
2026-02-21 2:09 ` [PATCH v5 24/38] gpu: nova-core: Hopper/Blackwell: add FSP secure boot completion waiting John Hubbard
2026-02-21 2:09 ` [PATCH v5 25/38] gpu: nova-core: Hopper/Blackwell: add FSP message structures John Hubbard
2026-02-21 2:09 ` [PATCH v5 26/38] gpu: nova-core: Hopper/Blackwell: add FMC signature extraction John Hubbard
2026-02-21 2:09 ` [PATCH v5 27/38] gpu: nova-core: Hopper/Blackwell: add FSP send/receive messaging John Hubbard
2026-02-21 2:09 ` [PATCH v5 28/38] gpu: nova-core: Hopper/Blackwell: add FspCotVersion type John Hubbard
2026-02-21 2:09 ` [PATCH v5 29/38] gpu: nova-core: Hopper/Blackwell: larger non-WPR heap John Hubbard
2026-02-21 2:09 ` [PATCH v5 30/38] gpu: nova-core: Hopper/Blackwell: add FSP Chain of Trust boot John Hubbard
2026-02-21 2:09 ` [PATCH v5 31/38] gpu: nova-core: Blackwell: use correct sysmem flush registers John Hubbard
2026-02-21 2:09 ` [PATCH v5 32/38] gpu: nova-core: Hopper/Blackwell: larger WPR2 (GSP) heap John Hubbard
2026-02-21 2:09 ` [PATCH v5 33/38] gpu: nova-core: refactor SEC2 booter loading into BooterFirmware::run() John Hubbard
2026-02-21 2:09 ` [PATCH v5 34/38] gpu: nova-core: Hopper/Blackwell: add GSP lockdown release polling John Hubbard
2026-02-21 2:09 ` [PATCH v5 35/38] gpu: nova-core: Hopper/Blackwell: new location for PCI config mirror John Hubbard
2026-02-21 2:09 ` John Hubbard [this message]
2026-02-21 2:09 ` [PATCH v5 37/38] rust: sizes: add u64 variants of SZ_* constants John Hubbard
2026-02-21 2:09 ` [PATCH v5 38/38] gpu: nova-core: use SZ_*_U64 constants from kernel::sizes 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=20260221020952.412352-37-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=joelagnelf@nvidia.com \
--cc=linux-kernel@vger.kernel.org \
--cc=lossin@kernel.org \
--cc=nouveau@lists.freedesktop.org \
--cc=ojeda@kernel.org \
--cc=rust-for-linux@vger.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