gpu: nova-core: correct FRTS vidmem offset calculation

Currently, the frts vidmem offset is calculated based on the non-wpr
heap size and pmu reservation size, but this is not right. The layout
actually looks like this:

| non-wpr heap | WPR2 .. FRTS | PMU reserved | ... | VGA workspace |

It's just by coincidence + generous alignment that the values happened
to match. Instead, define a per-architecture reserved size at the end of
the framebuffer and use this plus the PMU reserved size to calculate the
frts vidmem offset.

Fixes: d317e4585f ("gpu: nova-core: Hopper/Blackwell: add FSP Chain of Trust boot")
Signed-off-by: Eliot Courtney <ecourtney@nvidia.com>
Link: https://patch.msgid.link/20260804-blackwell-fixes-v4-1-ac858b6a1935@nvidia.com
[acourbot: add comment clarifying reason for testing pmu_reserved_size.]
[acourbot: make fb_end_reserved_size() return u64.]
Signed-off-by: Alexandre Courbot <acourbot@nvidia.com>
This commit is contained in:
Eliot Courtney 2026-08-04 14:41:12 +09:00 committed by Alexandre Courbot
parent 44e7e7f7cf
commit 5c9deba557
7 changed files with 48 additions and 10 deletions

View File

@ -80,6 +80,7 @@ fn write_sysmem_flush_page_gb100(bar: Bar0<'_>, addr: Bounded<u64, 52>) {
);
}
// This PMU reservation size is r570-specific.
pub(super) const fn pmu_reserved_size_gb100() -> u32 {
usize_into_u32::<{ const_align_up(SZ_8M + SZ_16M + SZ_4K, Alignment::new::<SZ_128K>()).unwrap() }>(
)

View File

@ -73,6 +73,7 @@ fn pmu_reserved_size(&self) -> u32 {
fn non_wpr_heap_size(&self) -> u32 {
// Non-WPR heap for GB20x (see Open RM: kgspGetNonWprHeapSize, GB202+).
// This size is r570-specific.
u32::SZ_2M + u32::SZ_128K
}

View File

@ -251,20 +251,32 @@ struct FspCotMessage {
}
impl FspCotMessage {
/// Computes the FRTS vidmem offset for the Chain-of-Trust message. It is measured backwards
/// from the end of the framebuffer.
fn frts_vidmem_offset(hal: &dyn hal::FspHal, fb_layout: &FbLayout) -> Result<u64> {
let mut offset = hal.fb_end_reserved_size();
// As per OpenRM's `kfspPrepareBootCommands_GH100`.
if fb_layout.pmu_reserved_size != 0 {
offset = (offset + u64::from(fb_layout.pmu_reserved_size))
// The 2 MiB alignment is r570-specific.
.align_up(Alignment::new::<SZ_2M>())
.ok_or(EINVAL)?;
}
Ok(offset)
}
/// Returns an in-place initializer for [`FspCotMessage`].
fn new<'a>(
fb_layout: &FbLayout,
fsp_fw: &'a FspFirmware,
args: &'a FmcBootArgs<'_>,
) -> Result<impl Init<Self> + 'a> {
// frts_vidmem_offset is measured from the end of FB, so FRTS sits at
// (end of FB) - frts_vidmem_offset.
let frts_vidmem_offset = if !args.resume {
let frts_reserved_size = fb_layout.heap.len() + u64::from(fb_layout.pmu_reserved_size);
let hal = hal::fsp_hal(args.chipset).ok_or(ENOTSUPP)?;
frts_reserved_size
.align_up(Alignment::new::<SZ_2M>())
.ok_or(EINVAL)?
let frts_vidmem_offset = if !args.resume {
Self::frts_vidmem_offset(hal, fb_layout)?
} else {
0
};
@ -275,7 +287,7 @@ fn new<'a>(
0
};
let version = hal::fsp_hal(args.chipset).ok_or(ENOTSUPP)?.cot_version();
let version = hal.cot_version();
let size = num::usize_into_u16::<{ core::mem::size_of::<NvdmPayloadCot>() }>();
Ok(init!(Self {

View File

@ -19,6 +19,10 @@ pub(super) trait FspHal {
/// Returns the FSP Chain of Trust protocol version this chipset advertises.
fn cot_version(&self) -> u16;
// TODO: consider moving this into the TLV firmware metadata when ready
/// Returns the size reserved at the end of the framebuffer, in bytes.
fn fb_end_reserved_size(&self) -> u64;
}
/// Returns the FSP HAL, or `None` if the architecture doesn't support FSP.

View File

@ -1,6 +1,8 @@
// SPDX-License-Identifier: GPL-2.0
// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
use kernel::sizes::SizeConstants;
use crate::{
driver::Bar0,
fsp::hal::FspHal, //
@ -17,6 +19,10 @@ fn fsp_boot_status(&self, bar: Bar0<'_>) -> u32 {
fn cot_version(&self) -> u16 {
2
}
fn fb_end_reserved_size(&self) -> u64 {
u64::SZ_2M + u64::SZ_128K
}
}
const GB100: Gb100 = Gb100;

View File

@ -1,7 +1,10 @@
// SPDX-License-Identifier: GPL-2.0
// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
use kernel::io::Io;
use kernel::{
io::Io,
sizes::SizeConstants, //
};
use crate::{
driver::Bar0,
@ -21,6 +24,10 @@ fn fsp_boot_status(&self, bar: Bar0<'_>) -> u32 {
fn cot_version(&self) -> u16 {
2
}
fn fb_end_reserved_size(&self) -> u64 {
u64::SZ_2M + u64::SZ_128K
}
}
const GB202: Gb202 = Gb202;

View File

@ -1,7 +1,10 @@
// SPDX-License-Identifier: GPL-2.0
// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
use kernel::io::Io;
use kernel::{
io::Io,
sizes::SizeConstants, //
};
use crate::{
driver::Bar0,
@ -26,6 +29,10 @@ fn fsp_boot_status(&self, bar: Bar0<'_>) -> u32 {
fn cot_version(&self) -> u16 {
1
}
fn fb_end_reserved_size(&self) -> u64 {
u64::SZ_2M
}
}
const GH100: Gh100 = Gh100;