Skip to content

Commit 82eaa14

Browse files
johnhubbardGnurou
authored andcommitted
gpu: nova-core: Hopper/Blackwell: add FSP secure boot completion waiting
Hopper and Blackwell use FSP instead of SEC2 for secure boot. The driver must wait for FSP secure boot to complete before continuing with GSP bring-up. Poll for boot success with a 5-second timeout, and return the FSP interface only on success so that later Chain of Trust operations cannot run before FSP is ready. The interface owns the FSP falcon and the FMC firmware. Signed-off-by: John Hubbard <jhubbard@nvidia.com> Reviewed-by: Eliot Courtney <ecourtney@nvidia.com> Link: https://patch.msgid.link/20260602032111.224790-13-jhubbard@nvidia.com [acourbot: use `inspect_err` instead of `map_err` and display actual error] [acourbot: limit visibility of `fsp_hal` to `super``] Co-developed-by: Alexandre Courbot <acourbot@nvidia.com> Signed-off-by: Alexandre Courbot <acourbot@nvidia.com>
1 parent 4257d31 commit 82eaa14

8 files changed

Lines changed: 186 additions & 3 deletions

File tree

drivers/gpu/nova-core/falcon/fsp.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ use crate::falcon::{
1515
};
1616

1717
/// Type specifying the `Fsp` falcon engine. Cannot be instantiated.
18-
#[expect(dead_code)]
1918
pub(crate) struct Fsp(());
2019

2120
impl RegisterBase<PFalconBase> for Fsp {

drivers/gpu/nova-core/fsp.rs

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3+
4+
//! FSP (Foundation Security Processor) interface for Hopper/Blackwell GPUs.
5+
//!
6+
//! Hopper/Blackwell use a simplified firmware boot sequence: FMC, then FSP, then GSP.
7+
//! Unlike Turing/Ampere/Ada, there is no SEC2 (Security Engine 2) usage.
8+
//! FSP handles secure boot directly using FMC firmware and Chain of Trust.
9+
10+
use kernel::{
11+
device,
12+
io::poll::read_poll_timeout,
13+
prelude::*,
14+
time::Delta, //
15+
};
16+
17+
use crate::{
18+
driver::Bar0,
19+
falcon::{
20+
fsp::Fsp as FspEngine,
21+
Falcon, //
22+
},
23+
firmware::fsp::FspFirmware,
24+
gpu::Chipset,
25+
regs, //
26+
};
27+
28+
mod hal;
29+
30+
/// FSP interface for Hopper/Blackwell GPUs.
31+
///
32+
/// An `Fsp` is produced by [`Fsp::wait_secure_boot`], which only returns once FSP secure boot
33+
/// has completed. It owns the FSP falcon and the FMC firmware, which are used for the subsequent
34+
/// Chain of Trust boot.
35+
pub(crate) struct Fsp {
36+
#[expect(dead_code)]
37+
falcon: Falcon<FspEngine>,
38+
#[expect(dead_code)]
39+
fsp_fw: FspFirmware,
40+
}
41+
42+
impl Fsp {
43+
/// Waits for FSP secure boot completion, then returns the [`Fsp`] interface.
44+
///
45+
/// Polls the thermal scratch register until FSP signals boot completion or the timeout
46+
/// elapses. Returning an [`Fsp`] only on success guarantees, at the API level, that the
47+
/// interface is not used before secure boot has completed.
48+
pub(crate) fn wait_secure_boot(
49+
dev: &device::Device<device::Bound>,
50+
bar: &Bar0,
51+
chipset: Chipset,
52+
fsp_fw: FspFirmware,
53+
) -> Result<Fsp> {
54+
/// FSP secure boot completion timeout in milliseconds.
55+
const FSP_SECURE_BOOT_TIMEOUT_MS: i64 = 5000;
56+
57+
let hal = hal::fsp_hal(chipset).ok_or(ENOTSUPP)?;
58+
let falcon = Falcon::<FspEngine>::new(dev, chipset)?;
59+
60+
read_poll_timeout(
61+
|| Ok(hal.fsp_boot_status(bar)),
62+
|&status| status == regs::NV_THERM_I2CS_SCRATCH_FSP_BOOT_COMPLETE_STATUS_SUCCESS,
63+
Delta::from_millis(10),
64+
Delta::from_millis(FSP_SECURE_BOOT_TIMEOUT_MS),
65+
)
66+
.inspect_err(|e| {
67+
dev_err!(dev, "FSP secure boot completion error: {:?}\n", e);
68+
})?;
69+
70+
Ok(Fsp { falcon, fsp_fw })
71+
}
72+
}

drivers/gpu/nova-core/fsp/hal.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3+
4+
use crate::{
5+
driver::Bar0,
6+
gpu::{
7+
Architecture,
8+
Chipset, //
9+
},
10+
};
11+
12+
mod gb202;
13+
mod gh100;
14+
15+
pub(super) trait FspHal {
16+
/// Returns the secure boot status from the architecture-specific `NV_THERM_I2CS_SCRATCH` register.
17+
fn fsp_boot_status(&self, bar: &Bar0) -> u32;
18+
}
19+
20+
/// Returns the FSP HAL, or `None` if the architecture doesn't support FSP.
21+
pub(super) fn fsp_hal(chipset: Chipset) -> Option<&'static dyn FspHal> {
22+
match chipset.arch() {
23+
Architecture::Turing | Architecture::Ampere | Architecture::Ada => None,
24+
Architecture::Hopper | Architecture::BlackwellGB10x => Some(gh100::GH100_HAL),
25+
Architecture::BlackwellGB20x => Some(gb202::GB202_HAL),
26+
}
27+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3+
4+
use kernel::io::Io;
5+
6+
use crate::{
7+
driver::Bar0,
8+
fsp::hal::FspHal,
9+
regs, //
10+
};
11+
12+
struct Gb202;
13+
14+
impl FspHal for Gb202 {
15+
fn fsp_boot_status(&self, bar: &Bar0) -> u32 {
16+
bar.read(regs::gb202::NV_THERM_I2CS_SCRATCH_FSP_BOOT_COMPLETE)
17+
.fsp_boot_complete()
18+
.into()
19+
}
20+
}
21+
22+
const GB202: Gb202 = Gb202;
23+
pub(super) const GB202_HAL: &dyn FspHal = &GB202;
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3+
4+
use kernel::io::Io;
5+
6+
use crate::{
7+
driver::Bar0,
8+
fsp::hal::FspHal,
9+
regs, //
10+
};
11+
12+
struct Gh100;
13+
14+
impl FspHal for Gh100 {
15+
fn fsp_boot_status(&self, bar: &Bar0) -> u32 {
16+
bar.read(regs::gh100::NV_THERM_I2CS_SCRATCH_FSP_BOOT_COMPLETE)
17+
.fsp_boot_complete()
18+
.into()
19+
}
20+
}
21+
22+
const GH100: Gh100 = Gh100;
23+
pub(super) const GH100_HAL: &dyn FspHal = &GH100;

drivers/gpu/nova-core/gsp/hal/gh100.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ use crate::{
2020
fsp::FspFirmware,
2121
FIRMWARE_VERSION, //
2222
},
23+
fsp::Fsp,
2324
gpu::Chipset,
2425
gsp::{
2526
boot::BootUnloadGuard,
@@ -40,14 +41,15 @@ impl GspHal for Gh100 {
4041
&self,
4142
_gsp: &'a Gsp,
4243
dev: &'a device::Device<device::Bound>,
43-
_bar: &'a Bar0,
44+
bar: &'a Bar0,
4445
chipset: Chipset,
4546
_fb_layout: &FbLayout,
4647
_wpr_meta: &Coherent<GspFwWprMeta>,
4748
_gsp_falcon: &'a Falcon<GspEngine>,
4849
_sec2_falcon: &'a Falcon<Sec2>,
4950
) -> Result<BootUnloadGuard<'a>> {
50-
let _fsp_fw = FspFirmware::new(dev, chipset, FIRMWARE_VERSION)?;
51+
let fsp_fw = FspFirmware::new(dev, chipset, FIRMWARE_VERSION)?;
52+
let _fsp = Fsp::wait_secure_boot(dev, bar, chipset, fsp_fw)?;
5153

5254
Err(ENOTSUPP)
5355
}

drivers/gpu/nova-core/nova_core.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ mod driver;
1717
mod falcon;
1818
mod fb;
1919
mod firmware;
20+
mod fsp;
2021
mod gpu;
2122
mod gsp;
2223
#[macro_use]

drivers/gpu/nova-core/regs.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -587,3 +587,39 @@ pub(crate) mod ga100 {
587587
}
588588
}
589589
}
590+
591+
pub(crate) const NV_THERM_I2CS_SCRATCH_FSP_BOOT_COMPLETE_STATUS_SUCCESS: u32 = 0xff;
592+
593+
pub(crate) mod gh100 {
594+
use kernel::io::register;
595+
596+
// PTHERM
597+
598+
register! {
599+
pub(crate) NV_THERM_I2CS_SCRATCH(u32) @ 0x000200bc {
600+
31:0 data;
601+
}
602+
603+
// Alias to `NV_THERM_I2CS_SCRATCH` when used to check for FSP boot completion.
604+
pub(crate) NV_THERM_I2CS_SCRATCH_FSP_BOOT_COMPLETE(u32) => NV_THERM_I2CS_SCRATCH {
605+
31:0 fsp_boot_complete;
606+
}
607+
}
608+
}
609+
610+
pub(crate) mod gb202 {
611+
use kernel::io::register;
612+
613+
// PTHERM
614+
615+
register! {
616+
pub(crate) NV_THERM_I2CS_SCRATCH(u32) @ 0x00ad00bc {
617+
31:0 data;
618+
}
619+
620+
// Alias to `NV_THERM_I2CS_SCRATCH` when used to check for FSP boot completion.
621+
pub(crate) NV_THERM_I2CS_SCRATCH_FSP_BOOT_COMPLETE(u32) => NV_THERM_I2CS_SCRATCH {
622+
31:0 fsp_boot_complete;
623+
}
624+
}
625+
}

0 commit comments

Comments
 (0)