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 v3 05/13] gpu: nova-core: place the generic bootloader at the top of IMEM
Date: Tue, 10 Nov 2026 19:20:54 +0900 [thread overview]
Message-ID: <20261110-r000-fw-v3-5-20d79ebb646f@nvidia.com> (raw)
In-Reply-To: <20261110-r000-fw-v3-0-20d79ebb646f@nvidia.com>
From: John Hubbard <jhubbard@nvidia.com>
The generic bootloader was loaded right below the first 64 KiB of IMEM,
on the assumption that every falcon it runs on has a 64 KiB IMEM. The
r000 load-and-execute bootloader event can name any image for it to
load, and the bootloader must then sit above the blocks that the image
occupies, that is, in the last blocks of IMEM, regardless of its size.
Place the bootloader at the top of the falcon's IMEM, using the IMEM
size that the HWCFG register reports, instead of assuming a 64 KiB IMEM.
The computation of `imem_dst_start` is moved to the `run` method as it
is the one that receives the Falcon as parameter.
Signed-off-by: John Hubbard <jhubbard@nvidia.com>
Reviewed-by: Timur Tabi <ttabi@nvidia.com>
Reviewed-by: Zhi Wang <zhiw@nvidia.com>
Reviewed-by: Eliot Courtney <ecourtney@nvidia.com>
[acourbot: split out of the patch separating the bootloader from FWSEC;
convert the IMEM size with usize::from()]
Signed-off-by: Alexandre Courbot <acourbot@nvidia.com>
---
drivers/gpu/nova-core/falcon.rs | 7 ++++
drivers/gpu/nova-core/firmware/gen_bootloader.rs | 42 +++++++++++++-----------
drivers/gpu/nova-core/regs.rs | 5 +++
3 files changed, 34 insertions(+), 20 deletions(-)
diff --git a/drivers/gpu/nova-core/falcon.rs b/drivers/gpu/nova-core/falcon.rs
index a34748abc74a..b17a997860ef 100644
--- a/drivers/gpu/nova-core/falcon.rs
+++ b/drivers/gpu/nova-core/falcon.rs
@@ -386,6 +386,13 @@ pub(crate) fn new(
})
}
+ /// Returns the size of this falcon's IMEM in bytes.
+ pub(crate) fn imem_size(&self) -> usize {
+ let blocks = usize::from(self.pfalcon.read(regs::NV_PFALCON_FALCON_HWCFG).imem_size());
+
+ blocks * MEM_BLOCK_ALIGNMENT
+ }
+
/// Resets DMA-related registers.
pub(crate) fn dma_reset(&self) {
self.pfalcon.update(regs::NV_PFALCON_FBIF_CTL, |v| {
diff --git a/drivers/gpu/nova-core/firmware/gen_bootloader.rs b/drivers/gpu/nova-core/firmware/gen_bootloader.rs
index 2f42d3ad1ba5..54d9796b4897 100644
--- a/drivers/gpu/nova-core/firmware/gen_bootloader.rs
+++ b/drivers/gpu/nova-core/firmware/gen_bootloader.rs
@@ -17,7 +17,6 @@
},
prelude::*,
ptr::Alignable,
- sizes,
transmute::AsBytes, //
};
@@ -133,20 +132,16 @@ unsafe impl AsBytes for BootloaderDmemDescV2 {}
pub(crate) struct GenericBootloader {
/// Bootloader code, zero-padded to a whole number of falcon memory blocks.
ucode: KVec<u8>,
- /// Byte offset in IMEM at which the code is loaded.
- imem_dst_start: Bounded<u32, 24>,
/// Tag under which the first code block is loaded.
start_tag: u16,
}
impl GenericBootloader {
- /// Loads the generic bootloader image for `chipset`, placed right below the first 64 KiB of
- /// IMEM.
+ /// Loads the generic bootloader image for `chipset`.
///
/// # Errors
///
/// - `EINVAL` if a required TLV field is absent.
- /// - `EOVERFLOW` if the image does not fit below 64 KiB.
/// - `ENOMEM` if the padded copy of the code cannot be allocated.
pub(crate) fn new(dev: &device::Device, chipset: Chipset) -> Result<Self> {
let fw = request_tlv(dev, chipset, "gen_bootloader")?;
@@ -172,15 +167,8 @@ pub(crate) fn new(dev: &device::Device, chipset: Chipset) -> Result<Self> {
ucode
};
- // The bootloader's code must be loaded in the area right below the first 64K of IMEM.
- const BOOTLOADER_LOAD_CEILING: usize = sizes::SZ_64K;
- let imem_dst_start = BOOTLOADER_LOAD_CEILING
- .checked_sub(ucode.len())
- .ok_or(EOVERFLOW)?;
-
Ok(Self {
ucode,
- imem_dst_start: imem_dst_start.try_into_bounded().ok_or(EINVAL)?,
start_tag: u16::try_from(tlv.get_u32(b"STRT")?)?,
})
}
@@ -191,11 +179,12 @@ fn boot_addr(&self) -> u32 {
u32::from(self.start_tag) << 8
}
- /// Returns the PIO parameters that place this bootloader in non-secure IMEM.
- fn imem_load_params(&self) -> FalconPioImemLoadTarget<'_> {
+ /// Returns the PIO parameters that place this bootloader in non-secure IMEM, at byte offset
+ /// `dst_start`.
+ fn imem_load_params(&self, dst_start: Bounded<u32, 24>) -> FalconPioImemLoadTarget<'_> {
FalconPioImemLoadTarget {
data: self.ucode.as_ref(),
- dst_start: self.imem_dst_start,
+ dst_start,
secure: false,
start_tag: self.start_tag,
}
@@ -203,9 +192,10 @@ fn imem_load_params(&self) -> FalconPioImemLoadTarget<'_> {
/// Runs the bootloader on `falcon` to load and start the image that `dmem_desc` names.
///
- /// The bootloader and the descriptor are loaded by PIO, the bootloader is started with `mbox0`
- /// in `MAILBOX0`, and this returns the mailbox values once the falcon has halted, that is,
- /// once the loaded image has run to completion.
+ /// The bootloader and the descriptor are loaded by PIO, the bootloader in the last blocks of
+ /// `falcon`'s IMEM. The bootloader is started with `mbox0` in `MAILBOX0`, and this returns the
+ /// mailbox values once the falcon has halted, that is, once the loaded image has run to
+ /// completion.
///
/// The caller is expected to reset `falcon` beforehand.
///
@@ -213,6 +203,7 @@ fn imem_load_params(&self) -> FalconPioImemLoadTarget<'_> {
///
/// - `ETIMEDOUT` if the falcon has not halted within two seconds of starting.
/// - `EINVAL` if `dmem_desc`'s DMA context isn't valid.
+ /// - `EOVERFLOW` if the bootloader does not fit in `falcon`'s IMEM.
///
/// Errors from the PIO load are propagated as-is.
pub(crate) fn run(
@@ -222,6 +213,14 @@ pub(crate) fn run(
target: FalconFbifTarget,
mbox0: u32,
) -> Result<(u32, u32)> {
+ // The top of IMEM, above the blocks that the bootloader loads the image into.
+ let imem_dst_start = falcon
+ .imem_size()
+ .checked_sub(self.ucode.len())
+ .ok_or(EOVERFLOW)?
+ .try_into_bounded()
+ .ok_or(EINVAL)?;
+
// 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(dmem_desc.ctx_dma))
@@ -234,6 +233,7 @@ pub(crate) fn run(
falcon.pio_load(&GenericBootloaderLoad {
bootloader: self,
+ imem_dst_start,
dmem_desc,
})?;
@@ -245,6 +245,8 @@ pub(crate) fn run(
/// firmware that [`Falcon::pio_load`] accepts.
struct GenericBootloaderLoad<'a> {
bootloader: &'a GenericBootloader,
+ /// Byte offset in IMEM at which the bootloader's code is loaded.
+ imem_dst_start: Bounded<u32, 24>,
dmem_desc: &'a BootloaderDmemDescV2,
}
@@ -272,7 +274,7 @@ fn imem_sec_load_params(&self) -> Option<FalconPioImemLoadTarget<'_>> {
}
fn imem_ns_load_params(&self) -> Option<FalconPioImemLoadTarget<'_>> {
- Some(self.bootloader.imem_load_params())
+ Some(self.bootloader.imem_load_params(self.imem_dst_start))
}
fn dmem_load_params(&self) -> FalconPioDmemLoadTarget<'_> {
diff --git a/drivers/gpu/nova-core/regs.rs b/drivers/gpu/nova-core/regs.rs
index bf3a43f1c09e..af0bbb92e992 100644
--- a/drivers/gpu/nova-core/regs.rs
+++ b/drivers/gpu/nova-core/regs.rs
@@ -181,6 +181,11 @@ pub(crate) fn usable_fb_size(self) -> u64 {
31:0 value => u32;
}
+ pub(crate) NV_PFALCON_FALCON_HWCFG(u32) @ 0x00000108 {
+ /// Number of 256-byte blocks in this falcon's IMEM.
+ 8:0 imem_size;
+ }
+
pub(crate) NV_PFALCON_FALCON_DMACTL(u32) @ 0x0000010c {
7:7 secure_stat => bool;
6:3 dmaq_num;
--
2.56.0
next prev parent reply other threads:[~2026-11-10 10:21 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-10 10:20 [PATCH v3 00/13] gpu: nova-core: generic bootloader and falcon DMA changes for r000 Alexandre Courbot
2026-11-10 10:20 ` [PATCH v3 01/13] gpu: nova-core: separate the generic falcon bootloader from FWSEC Alexandre Courbot
2026-11-10 10:20 ` [PATCH v3 02/13] gpu: nova-core: falcon: widen the IMEM PIO offset to 24 bits Alexandre Courbot
2026-11-10 10:20 ` [PATCH v3 03/13] gpu: nova-core: move the bootloader DMEM descriptor out of FWSEC Alexandre Courbot
2026-11-10 10:20 ` [PATCH v3 04/13] gpu: nova-core: run the generic bootloader from its own type Alexandre Courbot
2026-11-10 10:20 ` Alexandre Courbot [this message]
2026-11-10 10:20 ` [PATCH v3 06/13] rust: io: register: implement Copy and Clone for RegisterArrayLoc Alexandre Courbot
2026-11-10 10:20 ` [PATCH v3 07/13] gpu: nova-core: falcon: introduce and use with_fbif_transcfg Alexandre Courbot
2026-11-10 10:20 ` [PATCH v3 08/13] gpu: nova-core: falcon: rename the local variables of dma_wr() Alexandre Courbot
2026-11-10 10:20 ` [PATCH v3 09/13] gpu: nova-core: falcon: allow DMEM DMA transfers to request tagging Alexandre Courbot
2026-11-10 10:20 ` [PATCH v3 10/13] gpu: nova-core: falcon: allow DMA transfers to read from a framebuffer address Alexandre Courbot
2026-11-10 10:21 ` [PATCH v3 11/13] gpu: nova-core: falcon: use src_start as FB offset for all DMA transfers Alexandre Courbot
2026-11-10 10:21 ` [PATCH v3 12/13] gpu: nova-core: falcon: check the per-block DMA offsets for overflow Alexandre Courbot
2026-11-10 10:21 ` [PATCH v3 13/13] 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=20261110-r000-fw-v3-5-20d79ebb646f@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®