From: Alexandre Courbot <acourbot@nvidia.com>
To: Danilo Krummrich <dakr@kernel.org>,
Alice Ryhl <aliceryhl@google.com>,
David Airlie <airlied@gmail.com>,
Simona Vetter <simona@ffwll.ch>
Cc: John Hubbard <jhubbard@nvidia.com>,
Alistair Popple <apopple@nvidia.com>,
Timur Tabi <ttabi@nvidia.com>,
Eliot Courtney <ecourtney@nvidia.com>,
Zhi Wang <zhiw@nvidia.com>,
nova-gpu@lists.linux.dev, rust-for-linux@vger.kernel.org,
linux-kernel@vger.kernel.org,
Alexandre Courbot <acourbot@nvidia.com>
Subject: [PATCH v2 04/12] gpu: nova-core: move the bootloader DMEM descriptor out of FWSEC
Date: Sat, 07 Nov 2026 18:48:00 +0900 [thread overview]
Message-ID: <20261107-r000-fw-v2-4-fb37cc5b20cd@nvidia.com> (raw)
In-Reply-To: <20261107-r000-fw-v2-0-fb37cc5b20cd@nvidia.com>
From: John Hubbard <jhubbard@nvidia.com>
The generic falcon bootloader reads its load parameters from a
descriptor that the driver places in DMEM. The r000 load-and-execute
bootloader event carries such a descriptor, so its handler will need the
descriptor type.
The descriptor was defined in the FWSEC code, which was its only user.
Move the definition, unchanged, into the generic bootloader module.
No functional changes.
Signed-off-by: John Hubbard <jhubbard@nvidia.com>
Reviewed-by: Eliot Courtney <ecourtney@nvidia.com>
[acourbot: keep the fields private, add a constructor and the ctx_dma()
accessor instead of making every field pub(crate)]
Signed-off-by: Alexandre Courbot <acourbot@nvidia.com>
---
drivers/gpu/nova-core/firmware/fwsec/bootloader.rs | 95 +++++-----------------
drivers/gpu/nova-core/firmware/gen_bootloader.rs | 94 ++++++++++++++++++++-
2 files changed, 112 insertions(+), 77 deletions(-)
diff --git a/drivers/gpu/nova-core/firmware/fwsec/bootloader.rs b/drivers/gpu/nova-core/firmware/fwsec/bootloader.rs
index 00f0d9704883..19e047f1c1ed 100644
--- a/drivers/gpu/nova-core/firmware/fwsec/bootloader.rs
+++ b/drivers/gpu/nova-core/firmware/fwsec/bootloader.rs
@@ -35,60 +35,16 @@
},
firmware::{
fwsec::FwsecFirmware,
- gen_bootloader::GenericBootloader, //
+ gen_bootloader::{
+ BootloaderDmemDescV2,
+ GenericBootloader, //
+ },
},
gpu::Chipset,
num::FromSafeCast, //
regs,
};
-/// Structure used by the boot-loader to load the rest of the code.
-///
-/// This has to be filled by the GPU driver and copied into DMEM at offset
-/// [`BootloaderDesc.dmem_load_off`].
-#[repr(C, packed)]
-#[derive(Debug, Clone)]
-struct BootloaderDmemDescV2 {
- /// Reserved, should always be first element.
- reserved: [u32; 4],
- /// 16B signature for secure code, 0s if no secure code.
- signature: [u32; 4],
- /// DMA context used by the bootloader while loading code/data.
- ctx_dma: u32,
- /// 256B-aligned physical FB address where code is located.
- code_dma_base: u64,
- /// Offset from `code_dma_base` where the non-secure code is located.
- ///
- /// Also used as destination IMEM offset of non-secure code as the DMA firmware object is
- /// expected to be a mirror image of its loaded state.
- ///
- /// Must be multiple of 256.
- non_sec_code_off: u32,
- /// Size of the non-secure code part.
- non_sec_code_size: u32,
- /// Offset from `code_dma_base` where the secure code is located (must be multiple of 256).
- ///
- /// Also used as destination IMEM offset of secure code as the DMA firmware object is expected
- /// to be a mirror image of its loaded state.
- ///
- /// Must be multiple of 256.
- sec_code_off: u32,
- /// Size of the secure code part.
- sec_code_size: u32,
- /// Code entry point invoked by the bootloader after code is loaded.
- code_entry_point: u32,
- /// 256B-aligned physical FB address where data is located.
- data_dma_base: u64,
- /// Size of data block (should be multiple of 256B).
- data_size: u32,
- /// Number of arguments to be passed to the target firmware being loaded.
- argc: u32,
- /// Arguments to be passed to the target firmware being loaded.
- argv: u32,
-}
-// SAFETY: This struct doesn't contain uninitialized bytes and doesn't have interior mutability.
-unsafe impl AsBytes for BootloaderDmemDescV2 {}
-
/// Wrapper for [`FwsecFirmware`] that includes the bootloader performing the actual load
/// operation.
pub(crate) struct FwsecFirmwareWithBl<'a> {
@@ -141,9 +97,6 @@ pub(crate) fn new(
};
let dmem_desc = {
- // Bootloader payload is in non-coherent system memory.
- const FALCON_DMAIDX_PHYS_SYS_NCOH: u32 = 4;
-
let imem_sec = firmware.imem_sec_load_params();
let imem_ns = firmware.imem_ns_load_params().ok_or(EINVAL)?;
let dmem = firmware.dmem_load_params();
@@ -155,30 +108,20 @@ pub(crate) fn new(
return Err(EINVAL);
}
- BootloaderDmemDescV2 {
- reserved: [0; 4],
- signature: [0; 4],
- ctx_dma: FALCON_DMAIDX_PHYS_SYS_NCOH,
- code_dma_base: firmware_dma.dma_address(),
- // `dst_start` is also valid as the source offset since the firmware DMA object is
- // a mirror image of the target IMEM layout.
- non_sec_code_off: imem_ns.dst_start,
- non_sec_code_size: imem_ns.len,
- // `dst_start` is also valid as the source offset since the firmware DMA object is
- // a mirror image of the target IMEM layout.
- sec_code_off: imem_sec.dst_start,
- sec_code_size: imem_sec.len,
- code_entry_point: 0,
- // Start of data section is the added padding + the DMEM `src_start` field.
- data_dma_base: firmware_dma
- .dma_address()
- .checked_add(u64::from_safe_cast(align_padding))
- .and_then(|offset| offset.checked_add(dmem.src_start.into()))
- .ok_or(EOVERFLOW)?,
- data_size: dmem.len,
- argc: 0,
- argv: 0,
- }
+ // Start of data section is the added padding + the DMEM `src_start` field.
+ let data_dma_base = firmware_dma
+ .dma_address()
+ .checked_add(u64::from_safe_cast(align_padding))
+ .and_then(|offset| offset.checked_add(dmem.src_start.into()))
+ .ok_or(EOVERFLOW)?;
+
+ BootloaderDmemDescV2::new(
+ &imem_ns,
+ &imem_sec,
+ &dmem,
+ firmware_dma.dma_address(),
+ data_dma_base,
+ )
};
Ok(Self {
@@ -204,7 +147,7 @@ pub(crate) fn run(&self, dev: &Device<device::Bound>, falcon: &Falcon<'_, Gsp>)
// Configure DMA index for the bootloader to fetch the FWSEC firmware from system memory.
falcon.pfalcon.update(
- regs::NV_PFALCON_FBIF_TRANSCFG::try_at(usize::from_safe_cast(self.dmem_desc.ctx_dma))
+ regs::NV_PFALCON_FBIF_TRANSCFG::try_at(usize::from_safe_cast(self.dmem_desc.ctx_dma()))
.ok_or(EINVAL)?,
|v| {
v.with_target(FalconFbifTarget::CoherentSysmem)
diff --git a/drivers/gpu/nova-core/firmware/gen_bootloader.rs b/drivers/gpu/nova-core/firmware/gen_bootloader.rs
index c4f436104326..f769b2b277c0 100644
--- a/drivers/gpu/nova-core/firmware/gen_bootloader.rs
+++ b/drivers/gpu/nova-core/firmware/gen_bootloader.rs
@@ -12,7 +12,8 @@
TryIntoBounded, //
},
prelude::*,
- ptr::Alignable, //
+ ptr::Alignable,
+ transmute::AsBytes, //
};
use crate::{
@@ -20,6 +21,7 @@
self,
gsp::Gsp,
Falcon,
+ FalconDmaLoadTarget,
FalconPioImemLoadTarget, //
},
firmware::tlv::{
@@ -30,6 +32,96 @@
num::FromSafeCast, //
};
+/// Structure used by the boot-loader to load the rest of the code.
+///
+/// This has to be filled by the GPU driver and copied into DMEM at offset
+/// [`BootloaderDesc.dmem_load_off`].
+#[repr(C, packed)]
+#[derive(Debug, Clone)]
+pub(crate) struct BootloaderDmemDescV2 {
+ /// Reserved, should always be first element.
+ reserved: [u32; 4],
+ /// 16B signature for secure code, 0s if no secure code.
+ signature: [u32; 4],
+ /// DMA context used by the bootloader while loading code/data.
+ ctx_dma: u32,
+ /// 256B-aligned physical FB address where code is located.
+ code_dma_base: u64,
+ /// Offset from `code_dma_base` where the non-secure code is located.
+ ///
+ /// Also used as destination IMEM offset of non-secure code as the DMA firmware object is
+ /// expected to be a mirror image of its loaded state.
+ ///
+ /// Must be multiple of 256.
+ non_sec_code_off: u32,
+ /// Size of the non-secure code part.
+ non_sec_code_size: u32,
+ /// Offset from `code_dma_base` where the secure code is located (must be multiple of 256).
+ ///
+ /// Also used as destination IMEM offset of secure code as the DMA firmware object is expected
+ /// to be a mirror image of its loaded state.
+ ///
+ /// Must be multiple of 256.
+ sec_code_off: u32,
+ /// Size of the secure code part.
+ sec_code_size: u32,
+ /// Code entry point invoked by the bootloader after code is loaded.
+ code_entry_point: u32,
+ /// 256B-aligned physical FB address where data is located.
+ data_dma_base: u64,
+ /// Size of data block (should be multiple of 256B).
+ data_size: u32,
+ /// Number of arguments to be passed to the target firmware being loaded.
+ argc: u32,
+ /// Arguments to be passed to the target firmware being loaded.
+ argv: u32,
+}
+
+impl BootloaderDmemDescV2 {
+ /// Context DMA slot through which the bootloader reads the image: physical, non-coherent
+ /// system memory.
+ const FALCON_DMAIDX_PHYS_SYS_NCOH: u32 = 4;
+
+ /// Creates the descriptor of an image whose code is at `code_dma_base` and whose data is at
+ /// `data_dma_base`.
+ ///
+ /// `imem_ns` and `imem_sec` locate the non-secure and secure code in the image, and `dmem`
+ /// gives the size of its data. The code DMA object must be a mirror image of the target IMEM
+ /// layout, because the bootloader uses the destination offset of each code segment as its
+ /// source offset too.
+ pub(crate) fn new(
+ imem_ns: &FalconDmaLoadTarget,
+ imem_sec: &FalconDmaLoadTarget,
+ dmem: &FalconDmaLoadTarget,
+ code_dma_base: u64,
+ data_dma_base: u64,
+ ) -> Self {
+ Self {
+ reserved: [0; 4],
+ signature: [0; 4],
+ ctx_dma: Self::FALCON_DMAIDX_PHYS_SYS_NCOH,
+ code_dma_base,
+ non_sec_code_off: imem_ns.dst_start,
+ non_sec_code_size: imem_ns.len,
+ sec_code_off: imem_sec.dst_start,
+ sec_code_size: imem_sec.len,
+ code_entry_point: 0,
+ data_dma_base,
+ data_size: dmem.len,
+ argc: 0,
+ argv: 0,
+ }
+ }
+
+ /// Returns the context DMA slot through which the bootloader reads the image.
+ pub(crate) fn ctx_dma(&self) -> u32 {
+ self.ctx_dma
+ }
+}
+
+// SAFETY: This struct doesn't contain uninitialized bytes and doesn't have interior mutability.
+unsafe impl AsBytes for BootloaderDmemDescV2 {}
+
/// The generic falcon bootloader image and its IMEM load parameters.
pub(crate) struct GenericBootloader {
/// Bootloader code, zero-padded to a whole number of falcon memory blocks.
--
2.56.0
next prev parent reply other threads:[~2026-11-07 9:48 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-07 9:47 [PATCH v2 00/12] gpu: nova-core: generic bootloader and falcon DMA changes for r000 Alexandre Courbot
2026-11-07 9:47 ` [PATCH v2 01/12] gpu: nova-core: separate the generic falcon bootloader from FWSEC Alexandre Courbot
2026-11-07 9:47 ` [PATCH v2 02/12] gpu: nova-core: falcon: widen the IMEM PIO offset to 24 bits Alexandre Courbot
2026-11-07 9:47 ` [PATCH v2 03/12] gpu: nova-core: place the generic bootloader at the top of IMEM Alexandre Courbot
2026-11-07 9:48 ` Alexandre Courbot [this message]
2026-11-07 9:48 ` [PATCH v2 05/12] gpu: nova-core: run the generic bootloader from its own type Alexandre Courbot
2026-11-07 9:48 ` [PATCH v2 06/12] rust: io: register: implement Copy and Clone for RegisterArrayLoc Alexandre Courbot
2026-11-07 9:48 ` [PATCH v2 07/12] gpu: nova-core: falcon: introduce and use with_fbif_transcfg Alexandre Courbot
2026-11-07 9:48 ` [PATCH v2 08/12] gpu: nova-core: falcon: rename the local variables of dma_wr() Alexandre Courbot
2026-11-07 9:48 ` [PATCH v2 09/12] gpu: nova-core: falcon: allow DMEM DMA transfers to request tagging Alexandre Courbot
2026-11-07 9:48 ` [PATCH v2 10/12] gpu: nova-core: falcon: allow DMA transfers to read from a framebuffer address Alexandre Courbot
2026-11-07 9:48 ` [PATCH v2 11/12] gpu: nova-core: falcon: check the per-block DMA offsets for overflow Alexandre Courbot
2026-11-07 9:48 ` [PATCH v2 12/12] gpu: nova-core: falcon: program the FBIF_TRANSCFG register in dma_wr 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=20261107-r000-fw-v2-4-fb37cc5b20cd@nvidia.com \
--to=acourbot@nvidia.com \
--cc=airlied@gmail.com \
--cc=aliceryhl@google.com \
--cc=apopple@nvidia.com \
--cc=dakr@kernel.org \
--cc=ecourtney@nvidia.com \
--cc=jhubbard@nvidia.com \
--cc=linux-kernel@vger.kernel.org \
--cc=nova-gpu@lists.linux.dev \
--cc=rust-for-linux@vger.kernel.org \
--cc=simona@ffwll.ch \
--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®