Re: [PATCH 2/7] gpu: nova-core: place the generic bootloader at the top of IMEM
From: Alexandre Courbot
Date: Fri Nov 06 2026 - 06:08:22 EST
On Thu Nov 5, 2026 at 9:59 PM JST, Eliot Courtney wrote:
<...>
>> - pub(crate) fn new(dev: &device::Device<device::Bound>, chipset: Chipset) -> Result<Self> {
>> + pub(crate) fn new(
>> + dev: &device::Device<device::Bound>,
>> + chipset: Chipset,
>> + falcon: &Falcon<'_, Gsp>,
>> + ) -> Result<Self> {
>> let fw = request_tlv(dev, chipset, "gen_bootloader")?;
>> let tlv = Tlv::new(fw.data())?;
>> dev_dbg!(
>> @@ -68,9 +73,9 @@ pub(crate) fn new(dev: &device::Device<device::Bound>, chipset: Chipset) -> Resu
>> 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
>> + // The top of IMEM, above the blocks that the bootloader loads the image into.
>> + let imem_dst_start = falcon
>> + .imem_size()
>> .checked_sub(ucode.len())
>> .ok_or(EOVERFLOW)?;
>
> `imem_size` is 8:0 (so 9 bits), and multiplied by 256. So it can be max
> ~2^17. Then we subtract off ucode.len() and do u16::try_from, so that
> could fail. I don't know if any real hardware actually hits this though.
> This value (`imem_dst_start`) eventually gets written into
> NV_PFALCON_FALCON_IMEMC::offs which is 15:0 in nova. According to openrm
> though, it's 15:0 for turing, and after that it's 23:0. So maybe worth
> checking (then we'd widen `imem_dst_start` etc to u32). I think it
> probably 'just works' fine to switch to u32 and change
> NV_PFALCON_FALCON_IMEMC::offs to 23:0, even for turing, and would be the
> same behaviour as nouveau afaict.
Oh, nice catch. The bootloader only runs on Turing and GA100, and as you
pointed out on Turing `IMEMC::offs` is 16 bits, but on GA100 it will be 24
bits and if GA100 signals more than 64KB of IMEM then this will fail.
Widening the `IMEMC::offs` definition for all GPUs should just work
indeed, so let's do that. On Turing we are basically guaranteed that the
upper 8 bits will never be set. I'll use a `Bounded` to keep things
within the acceptable range as early as possible.