Various "reserved" areas of FB (frame buffer: vidmem) have to be calculated, because the GSP booting process needs this information.
The calculations are const, so a new const-compatible alignment function is also added to num.rs, in order to align the reserved areas. Cc: Timur Tabi <[email protected]> Cc: Gary Guo <[email protected]> Signed-off-by: John Hubbard <[email protected]> --- drivers/gpu/nova-core/fb.rs | 18 ++++++++++++++++++ drivers/gpu/nova-core/gsp/fw.rs | 6 +++++- drivers/gpu/nova-core/num.rs | 10 ++++++++++ 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/nova-core/fb.rs b/drivers/gpu/nova-core/fb.rs index e803e6e0cdb9..9b4407338724 100644 --- a/drivers/gpu/nova-core/fb.rs +++ b/drivers/gpu/nova-core/fb.rs @@ -170,6 +170,9 @@ pub(crate) struct FbLayout { pub(crate) wpr2: FbRange, pub(crate) heap: FbRange, pub(crate) vf_partition_count: u8, + /// Total reserved size (heap + PMU reserved), aligned to 2MB. + #[expect(unused)] + pub(crate) total_reserved_size: u32, } impl FbLayout { @@ -257,6 +260,16 @@ pub(crate) fn new(chipset: Chipset, bar: &Bar0, gsp_fw: &GspFirmware) -> Result< FbRange(wpr2.start - HEAP_SIZE..wpr2.start) }; + // Calculate reserved sizes. PMU reservation is a subset of the total reserved size. + let heap_size = (heap.end - heap.start) as u64; + let pmu_reserved_size = u64::from(PMU_RESERVED_SIZE); + + let total_reserved_size = { + let total = heap_size + pmu_reserved_size; + const RSVD_ALIGN: Alignment = Alignment::new::<SZ_2M>(); + total.align_up(RSVD_ALIGN).ok_or(EINVAL)? + }; + Ok(Self { fb, vga_workspace, @@ -267,6 +280,11 @@ pub(crate) fn new(chipset: Chipset, bar: &Bar0, gsp_fw: &GspFirmware) -> Result< wpr2, heap, vf_partition_count: 0, + total_reserved_size: total_reserved_size as u32, }) } } + +/// PMU reserved size, aligned to 128KB. +pub(crate) const PMU_RESERVED_SIZE: u32 = + crate::num::const_align_up::<SZ_128K>(SZ_8M + SZ_16M + SZ_4K) as u32; diff --git a/drivers/gpu/nova-core/gsp/fw.rs b/drivers/gpu/nova-core/gsp/fw.rs index 83ff91614e36..086153edfa86 100644 --- a/drivers/gpu/nova-core/gsp/fw.rs +++ b/drivers/gpu/nova-core/gsp/fw.rs @@ -27,7 +27,10 @@ }; use crate::{ - fb::FbLayout, + fb::{ + FbLayout, + PMU_RESERVED_SIZE, // + }, firmware::gsp::GspFirmware, gpu::Chipset, gsp::{ @@ -183,6 +186,7 @@ pub(crate) fn new(gsp_firmware: &GspFirmware, fb_layout: &FbLayout) -> Self { fbSize: fb_layout.fb.end - fb_layout.fb.start, vgaWorkspaceOffset: fb_layout.vga_workspace.start, vgaWorkspaceSize: fb_layout.vga_workspace.end - fb_layout.vga_workspace.start, + pmuReservedSize: PMU_RESERVED_SIZE, ..Default::default() }) } diff --git a/drivers/gpu/nova-core/num.rs b/drivers/gpu/nova-core/num.rs index c952a834e662..f068722c5bdf 100644 --- a/drivers/gpu/nova-core/num.rs +++ b/drivers/gpu/nova-core/num.rs @@ -215,3 +215,13 @@ pub(crate) const fn [<$from _into_ $into>]<const N: $from>() -> $into { impl_const_into!(u64 => { u8, u16, u32 }); impl_const_into!(u32 => { u8, u16 }); impl_const_into!(u16 => { u8 }); + +/// Aligns `value` up to `ALIGN` at compile time. +/// +/// This is the const-compatible equivalent of [`kernel::ptr::Alignable::align_up`]. +/// `ALIGN` must be a power of two (enforced at compile time). +#[inline(always)] +pub(crate) const fn const_align_up<const ALIGN: usize>(value: usize) -> usize { + build_assert!(ALIGN.is_power_of_two()); + (value + (ALIGN - 1)) & !(ALIGN - 1) +} -- 2.52.0
