mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: "Alexandre Courbot" <acourbot@nvidia.com>
To: "Eliot Courtney" <ecourtney@nvidia.com>
Cc: "Danilo Krummrich" <dakr@kernel.org>,
	"John Hubbard" <jhubbard@nvidia.com>,
	"Timur Tabi" <ttabi@nvidia.com>,
	"Alistair Popple" <apopple@nvidia.com>,
	"Shashank Sharma" <shashanks@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>, "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>,
	"Boqun Feng" <boqun@kernel.org>
Subject: Re: [PATCH v13 7/9] gpu: nova-core: Hopper/Blackwell: add GSP lockdown release polling
Date: Wed, 03 Jun 2026 23:53:51 +0900	[thread overview]
Message-ID: <DIZI0NBFRIHQ.1VNJD1LZBX80G@nvidia.com> (raw)
In-Reply-To: <DIZE6PDLOCHP.ITQSKNYRZ7H1@nvidia.com>

On Wed Jun 3, 2026 at 8:53 PM JST, Eliot Courtney wrote:
> On Wed Jun 3, 2026 at 7:17 PM JST, Alexandre Courbot wrote:
>> On Wed Jun 3, 2026 at 4:30 PM JST, Alexandre Courbot wrote:
>>> From: John Hubbard <jhubbard@nvidia.com>
>>>
>>> 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 <jhubbard@nvidia.com>
>>> Signed-off-by: Alexandre Courbot <acourbot@nvidia.com>
>>> ---
>>>  drivers/gpu/nova-core/falcon/gsp.rs    |  6 +++
>>>  drivers/gpu/nova-core/fsp.rs           |  6 +++
>>>  drivers/gpu/nova-core/gsp/hal/gh100.rs | 88 +++++++++++++++++++++++++++++++++-
>>>  drivers/gpu/nova-core/regs.rs          |  2 +
>>>  4 files changed, 100 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/drivers/gpu/nova-core/falcon/gsp.rs b/drivers/gpu/nova-core/falcon/gsp.rs
>>> index df6d5a382c7a..136d6b24103f 100644
>>> --- a/drivers/gpu/nova-core/falcon/gsp.rs
>>> +++ b/drivers/gpu/nova-core/falcon/gsp.rs
>>> @@ -57,4 +57,10 @@ pub(crate) fn check_reload_completed(&self, bar: &Bar0, timeout: Delta) -> Resul
>>>          )
>>>          .map(|_| true)
>>>      }
>>> +
>>> +    /// Returns whether the RISC-V branch privilege lockdown bit is set.
>>> +    pub(crate) fn riscv_branch_privilege_lockdown(&self, bar: &Bar0) -> bool {
>>> +        bar.read(regs::NV_PFALCON_FALCON_HWCFG2::of::<Gsp>())
>>> +            .riscv_br_priv_lockdown()
>>> +    }
>>>  }
>>> diff --git a/drivers/gpu/nova-core/fsp.rs b/drivers/gpu/nova-core/fsp.rs
>>> index 883ac4f8b811..872898ffe0a3 100644
>>> --- a/drivers/gpu/nova-core/fsp.rs
>>> +++ b/drivers/gpu/nova-core/fsp.rs
>>> @@ -184,6 +184,12 @@ pub(crate) fn new(
>>>              resume,
>>>          })
>>>      }
>>> +
>>> +    /// DMA address of the FMC boot parameters, needed after boot for lockdown
>>> +    /// release polling.
>>> +    pub(crate) fn boot_params_dma_handle(&self) -> u64 {
>>> +        self.fmc_boot_params.dma_handle()
>>> +    }
>>>  }
>>>  
>>>  /// FSP interface for Hopper/Blackwell GPUs.
>>> diff --git a/drivers/gpu/nova-core/gsp/hal/gh100.rs b/drivers/gpu/nova-core/gsp/hal/gh100.rs
>>> index f41f3fea15ff..def41745a30f 100644
>>> --- a/drivers/gpu/nova-core/gsp/hal/gh100.rs
>>> +++ b/drivers/gpu/nova-core/gsp/hal/gh100.rs
>>> @@ -5,7 +5,9 @@
>>>  
>>>  use kernel::{
>>>      device,
>>> -    dma::Coherent, //
>>> +    dma::Coherent,
>>> +    io::poll::read_poll_timeout,
>>> +    time::Delta, //
>>>  };
>>>  
>>>  use crate::{
>>> @@ -33,6 +35,86 @@
>>>      },
>>>  };
>>>  
>>> +/// GSP lockdown pattern written by firmware to mbox0 while RISC-V branch privilege
>>> +/// lockdown is active. The low byte varies, the upper 24 bits are fixed.
>>> +const GSP_LOCKDOWN_PATTERN: u32 = 0xbadf_4100;
>>> +const GSP_LOCKDOWN_MASK: u32 = 0xffff_ff00;
>
> nit: these constants can be moved into impl GspMbox or made local to
> `is_locked_down`
>
>>> +
>>> +/// GSP falcon mailbox state, used to track lockdown release status.
>>> +struct GspMbox {
>>> +    mbox0: u32,
>>> +    mbox1: u32,
>>> +}
>>> +
>>> +impl GspMbox {
>>> +    /// Reads both mailboxes from the GSP falcon.
>>> +    fn read(gsp_falcon: &Falcon<GspEngine>, bar: &Bar0) -> Self {
>>> +        Self {
>>> +            mbox0: gsp_falcon.read_mailbox0(bar),
>>> +            mbox1: gsp_falcon.read_mailbox1(bar),
>>> +        }
>>> +    }
>>> +
>>> +    /// Returns `true` if the lockdown pattern is present in `mbox0`.
>>> +    fn is_locked_down(&self) -> bool {
>>> +        (self.mbox0 & GSP_LOCKDOWN_MASK) == GSP_LOCKDOWN_PATTERN
>>> +    }
>>> +
>>> +    /// Combines mailbox0 and mailbox1 into a 64-bit address.
>>> +    fn combined_addr(&self) -> u64 {
>>> +        (u64::from(self.mbox1) << 32) | u64::from(self.mbox0)
>>> +    }
>>> +
>>> +    /// Returns `true` if GSP lockdown has been released.
>>> +    ///
>>> +    /// Checks the lockdown pattern, validates the boot params address,
>>> +    /// and verifies the `HWCFG2` lockdown bit is clear.
>>> +    fn lockdown_released(
>>> +        &self,
>>> +        gsp_falcon: &Falcon<GspEngine>,
>>> +        bar: &Bar0,
>>> +        fmc_boot_params_addr: u64,
>>> +    ) -> bool {
>>> +        if self.is_locked_down() {
>>> +            return false;
>>> +        }
>>> +
>>> +        if self.mbox0 != 0 && self.combined_addr() != fmc_boot_params_addr {
>>> +            return true;
>>> +        }
>>
>> This looks like a bug - if the mailboxes still contain the boot
>> parameters address, we will keep going and might return true on the next
>> line, which the caller will interpret as an error. OpenRM does the
>> opposite check and has an additional test for `mailbox0 != 0`, which we
>> can translate into this logic:
>>
>>     if self.mbox0 != 0 {
>>         return self.combined_addr() != fmc_boot_params_addr;
>>     }
>>
>> I'll fix it and add a few comments explaining what the code does as it
>> can be a bit convoluted.
>
> Yeah, I agree. I think the logic openrm uses is like:
>
> 1. wait until HWCFG2 != 0 && (HWCFG2 & 0xffffff00) != 0xbadf4100
> 2. wait until mbox0 == 0 || addr != fmc_boot_params_addr
> 3. wait until riscv_br_priv_lockdown == 0 || mbox0 != 0
>
> So several things are different to openrm (not sure if they are wrong
> though):
>
> 1. `is_locked_down` is checking the wrong register (should check HWCFG2
>    AFAICT). I think we should name this more like
>    'gsp_mailboxes_readable' or something, since IIUC it is meant to test
>    when it's valid to read mboxs.
> 2. other logic is wrong as you mentioned.
>
> Maybe we could structure lockdown_released like this:
>
> // can't read the mailboxes yet (even though we already did but the
> // result is actually not valid so maybe this should be restructured)
> if !gsp_mailboxes_readable {
>   return false;
> }
>
> // we can read the registers and we are still waiting for mbox0 to
> // be zero
> if mbox0 != 0 && addr == fmc_boot_params_addr {
>   return false;
> }
>
> // either lockdown is released or some error happened
> return riscv_br_priv_lockdown == 0 || mbox0 != 0
>
> I think your suggested change w.r.t. if self.mbox0 != 0; is also
> correct. I think we should update the comment on the function and the
> function name too to say it returns true on lockdown release OR an error
> happened.
>
> I don't know if there's a simpler logic that will work, just commenting
> on how it compares to openrm.

Wow, the wrong register check in `is_locked_down` is pretty significant.
Thanks for catching this.

I'll fix the logic when applying; the resulting diff is a bit longer
than I wish it was, but not so scary.

diff --git a/drivers/gpu/nova-core/falcon/gsp.rs b/drivers/gpu/nova-core/falcon/gsp.rs
index 136d6b24103f..98a1c1dc8465 100644
--- a/drivers/gpu/nova-core/falcon/gsp.rs
+++ b/drivers/gpu/nova-core/falcon/gsp.rs
@@ -24,6 +24,10 @@
     regs,
 };
 
+/// Pattern returned by GSP register reads while the PRIV target mask still blocks CPU access.
+const GSP_TARGET_MASK_LOCKED_PATTERN: u32 = 0xbadf_4100;
+const GSP_TARGET_MASK_LOCKED_MASK: u32 = 0xffff_ff00;
+
 /// Type specifying the `Gsp` falcon engine. Cannot be instantiated.
 pub(crate) struct Gsp(());
 
@@ -63,4 +67,13 @@ pub(crate) fn riscv_branch_privilege_lockdown(&self, bar: &Bar0) -> bool {
         bar.read(regs::NV_PFALCON_FALCON_HWCFG2::of::<Gsp>())
             .riscv_br_priv_lockdown()
     }
+
+    /// Returns whether GSP registers can be read by the CPU.
+    pub(crate) fn priv_target_mask_released(&self, bar: &Bar0) -> bool {
+        let hwcfg2 = bar
+            .read(regs::NV_PFALCON_FALCON_HWCFG2::of::<Gsp>())
+            .into_raw();
+
+        hwcfg2 != 0 && (hwcfg2 & GSP_TARGET_MASK_LOCKED_MASK) != GSP_TARGET_MASK_LOCKED_PATTERN
+    }
 }
diff --git a/drivers/gpu/nova-core/gsp/hal/gh100.rs b/drivers/gpu/nova-core/gsp/hal/gh100.rs
index acdfb7fc06fc..57e31ef4819d 100644
--- a/drivers/gpu/nova-core/gsp/hal/gh100.rs
+++ b/drivers/gpu/nova-core/gsp/hal/gh100.rs
@@ -35,11 +35,6 @@
     },
 };
 
-/// GSP lockdown pattern written by firmware to mbox0 while RISC-V branch privilege
-/// lockdown is active. The low byte varies, the upper 24 bits are fixed.
-const GSP_LOCKDOWN_PATTERN: u32 = 0xbadf_4100;
-const GSP_LOCKDOWN_MASK: u32 = 0xffff_ff00;
-
 /// GSP falcon mailbox state, used to track lockdown release status.
 struct GspMbox {
     mbox0: u32,
@@ -55,30 +50,21 @@ fn read(gsp_falcon: &Falcon<GspEngine>, bar: &Bar0) -> Self {
         }
     }
 
-    /// Returns `true` if the lockdown pattern is present in `mbox0`.
-    fn is_locked_down(&self) -> bool {
-        (self.mbox0 & GSP_LOCKDOWN_MASK) == GSP_LOCKDOWN_PATTERN
-    }
-
     /// Combines mailbox0 and mailbox1 into a 64-bit address.
     fn combined_addr(&self) -> u64 {
         (u64::from(self.mbox1) << 32) | u64::from(self.mbox0)
     }
 
-    /// Returns `true` if GSP lockdown has been released.
+    /// Returns `true` if GSP lockdown has been released or a GSP-FMC error happened.
     ///
     /// Returns `true` both on successful lockdown release and on GSP-FMC-reported errors, since
     /// either condition should stop the poll loop.
-    fn lockdown_released(
+    fn lockdown_released_or_error(
         &self,
         gsp_falcon: &Falcon<GspEngine>,
         bar: &Bar0,
         fmc_boot_params_addr: u64,
     ) -> bool {
-        if self.is_locked_down() {
-            return false;
-        }
-
         // GSP-FMC normally clears the boot parameters address from the mailboxes early during
         // boot. If the address is still there, keep polling rather than treating it as an error.
         // Any other non-zero mailbox0 value is a GSP-FMC error code.
@@ -100,14 +86,25 @@ fn wait_for_gsp_lockdown_release(
     dev_dbg!(dev, "Waiting for GSP lockdown release\n");
 
     let mbox = read_poll_timeout(
-        || Ok(GspMbox::read(gsp_falcon, bar)),
-        |mbox| mbox.lockdown_released(gsp_falcon, bar, fmc_boot_params_addr),
+        || {
+            // While the PRIV target mask is still locked to FSP, GSP register and mailbox reads
+            // are not meaningful. Wait until HWCFG2 says the CPU can read them.
+            Ok(match gsp_falcon.priv_target_mask_released(bar) {
+                false => None,
+                true => Some(GspMbox::read(gsp_falcon, bar)),
+            })
+        },
+        |mbox| match mbox {
+            None => false,
+            Some(mbox) => mbox.lockdown_released_or_error(gsp_falcon, bar, fmc_boot_params_addr),
+        },
         Delta::from_millis(10),
         Delta::from_secs(30),
     )
     .inspect_err(|_| {
         dev_err!(dev, "GSP lockdown release timeout\n");
-    })?;
+    })?
+    .ok_or(EIO)?;
 
     // If polling stopped with a non-zero mailbox0, it was not the boot parameters address
     // anymore and therefore represents a GSP-FMC error code.

  reply	other threads:[~2026-06-03 14:54 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-06-03  7:30 [PATCH v13 0/9] gpu: nova-core: Hopper/Blackwell support Alexandre Courbot
2026-06-03  7:30 ` [PATCH v13 1/9] gpu: nova-core: Hopper/Blackwell: add FSP falcon EMEM operations Alexandre Courbot
2026-06-03 10:49   ` Eliot Courtney
2026-06-03  7:30 ` [PATCH v13 2/9] gpu: nova-core: Hopper/Blackwell: add FSP message infrastructure Alexandre Courbot
2026-06-03 10:50   ` Eliot Courtney
2026-06-03  7:30 ` [PATCH v13 3/9] gpu: nova-core: add MCTP/NVDM protocol types for firmware communication Alexandre Courbot
2026-06-03  7:30 ` [PATCH v13 4/9] gpu: nova-core: Hopper/Blackwell: add FSP send/receive messaging Alexandre Courbot
2026-06-03 10:57   ` Eliot Courtney
2026-06-03  7:30 ` [PATCH v13 5/9] gpu: nova-core: Hopper/Blackwell: select FSP Chain of Trust version Alexandre Courbot
2026-06-03  7:30 ` [PATCH v13 6/9] gpu: nova-core: Hopper/Blackwell: add FSP Chain of Trust boot Alexandre Courbot
2026-06-03 12:47   ` Eliot Courtney
2026-06-03 13:35     ` Alexandre Courbot
2026-06-03  7:30 ` [PATCH v13 7/9] gpu: nova-core: Hopper/Blackwell: add GSP lockdown release polling Alexandre Courbot
2026-06-03 10:17   ` Alexandre Courbot
2026-06-03 11:53     ` Eliot Courtney
2026-06-03 14:53       ` Alexandre Courbot [this message]
2026-06-03  7:30 ` [PATCH v13 8/9] gpu: nova-core: add non-sec2 unload path Alexandre Courbot
2026-06-03  7:30 ` [PATCH v13 9/9] gpu: nova-core: gsp: enable FSP boot path Alexandre Courbot
2026-06-03 11:04   ` Eliot Courtney
2026-06-03 15:04 ` [PATCH v13 0/9] gpu: nova-core: Hopper/Blackwell support Alexandre Courbot

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=DIZI0NBFRIHQ.1VNJD1LZBX80G@nvidia.com \
    --to=acourbot@nvidia.com \
    --cc=a.hindborg@kernel.org \
    --cc=airlied@gmail.com \
    --cc=aliceryhl@google.com \
    --cc=apopple@nvidia.com \
    --cc=bhelgaas@google.com \
    --cc=bjorn3_gh@protonmail.com \
    --cc=boqun@kernel.org \
    --cc=dakr@kernel.org \
    --cc=ecourtney@nvidia.com \
    --cc=gary@garyguo.net \
    --cc=jhubbard@nvidia.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=lossin@kernel.org \
    --cc=nova-gpu@lists.linux.dev \
    --cc=ojeda@kernel.org \
    --cc=shashanks@nvidia.com \
    --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

all inboxes | Powered by JetHome®