On Wed Dec 3, 2025 at 5:59 AM GMT, John Hubbard wrote:
> On Hopper and Blackwell, FSP boots GSP with hardware lockdown enabled.
> After FSP Chain of Trust completes, the driver must poll for lockdown
> release before proceeding with GSP initialization. Add the register
> bit and helper functions needed for this polling.
>
> Signed-off-by: John Hubbard <[email protected]>
> ---
> drivers/gpu/nova-core/gsp/boot.rs | 86 ++++++++++++++++++++++++++++++-
> drivers/gpu/nova-core/regs.rs | 1 +
> 2 files changed, 86 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/nova-core/gsp/boot.rs
> b/drivers/gpu/nova-core/gsp/boot.rs
> index 315f84907b11..4d04135a700e 100644
> --- a/drivers/gpu/nova-core/gsp/boot.rs
> +++ b/drivers/gpu/nova-core/gsp/boot.rs
> @@ -15,7 +15,8 @@
> falcon::{
> gsp::Gsp,
> sec2::Sec2,
> - Falcon, //
> + Falcon,
> + FalconEngine, //
> },
> fb::FbLayout,
> firmware::{
> @@ -154,6 +155,89 @@ fn run_booter(
> Ok(())
> }
>
> + /// Check if GSP lockdown has been released after FSP Chain of Trust
> + fn gsp_lockdown_released(
> + dev: &device::Device,
> + gsp_falcon: &Falcon<Gsp>,
> + bar: &Bar0,
> + fmc_boot_params_addr: u64,
> + mbox0: &mut u32,
> + ) -> bool {
> + // Read GSP falcon mailbox0
> + *mbox0 = gsp_falcon.read_mailbox0(bar);
> +
> + // Check 1: If mbox0 has 0xbadf4100 pattern, GSP is still locked down
> + if *mbox0 != 0 && (*mbox0 & 0xffffff00) == 0xbadf4100 {
> + return false;
> + }
> +
> + // Check 2: If mbox0 has a value, check if it's an error
> + if *mbox0 != 0 {
> + let mbox1 = gsp_falcon.read_mailbox1(bar);
> +
> + let combined_addr = (u64::from(mbox1) << 32) | u64::from(*mbox0);
> + if combined_addr != fmc_boot_params_addr {
> + // Address doesn't match - GSP wrote an error code
> + // Return TRUE (lockdown released) with error
> + dev_dbg!(dev,
> + "GSP lockdown released with error: mbox0={:#x},
> combined_addr={:#x}, expected={:#x}",
> + *mbox0, combined_addr, fmc_boot_params_addr);
> + return true;
> + }
> + }
> +
> + // Check 3: Verify HWCFG2 RISCV_BR_PRIV_LOCKDOWN bit is clear
> + let hwcfg2 = regs::NV_PFALCON_FALCON_HWCFG2::read(bar,
> &crate::falcon::gsp::Gsp::ID);
> + !hwcfg2.riscv_br_priv_lockdown()
> + }
> +
> + /// Wait for GSP lockdown to be released after FSP Chain of Trust
> + #[expect(dead_code)]
> + fn wait_for_gsp_lockdown_release(
> + dev: &device::Device,
> + bar: &Bar0,
> + gsp_falcon: &Falcon<Gsp>,
> + fmc_boot_params_addr: u64,
> + ) -> Result<u32> {
> + dev_dbg!(dev, "Waiting for GSP lockdown release\n");
> +
> + let mut mbox0: u32 = 0;
> +
> + read_poll_timeout(
> + || {
> + let released = Self::gsp_lockdown_released(
> + dev,
> + gsp_falcon,
> + bar,
> + fmc_boot_params_addr,
> + &mut mbox0,
> + );
> +
> + Ok((released, mbox0))
> + },
> + |(released, _)| *released,
> + Delta::ZERO,
> + Delta::from_millis(4000),
> + )
> + .inspect_err(|_| {
> + dev_err!(dev, "GSP lockdown release timeout\n");
> + })
Once you're done with the error, please just return early with `?` and not keep
chaining.
Best,
Gary
> + .map(|(_, mbox0)| mbox0)
> + .and_then(|mbox0| {
> + // Check mbox0 for error after wait completion
> + if mbox0 != 0 {
> + dev_err!(dev, "GSP-FMC boot failed (mbox: {:#x})\n", mbox0);
> + Err(EIO)
> + } else {
> + dev_dbg!(
> + dev,
> + "GSP hardware lockdown fully released, proceeding with
> initialization\n"
> + );
> + Ok(mbox0)
> + }
> + })
> + }
> +
> /// Attempt to boot the GSP.
> ///
> /// This is a GPU-dependent and complex procedure that involves loading
> firmware files from
> diff --git a/drivers/gpu/nova-core/regs.rs b/drivers/gpu/nova-core/regs.rs
> index 0d5c13f19073..a41d31449c65 100644
> --- a/drivers/gpu/nova-core/regs.rs
> +++ b/drivers/gpu/nova-core/regs.rs
> @@ -277,6 +277,7 @@ pub(crate) fn vga_workspace_addr(self) -> Option<u64> {
>
> register!(NV_PFALCON_FALCON_HWCFG2 @ PFalconBase[0x000000f4] {
> 10:10 riscv as bool;
> + 11:11 riscv_br_priv_lockdown as bool, "RISC-V branch privilege
> lockdown bit";
> 12:12 mem_scrubbing as bool, "Set to 0 after memory scrubbing is
> completed";
> 31:31 reset_ready as bool, "Signal indicating that reset is completed
> (GA102+)";
> });