|
| 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 | +} |
0 commit comments