Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

gpu: nova-core: gsp: Create wpr metadata

The GSP requires some pieces of metadata to boot. These are passed in a
struct which the GSP transfers via DMA. Create this struct and get a
handle to it for future use when booting the GSP.

Signed-off-by: Alistair Popple <apopple@nvidia.com>
Co-developed-by: Alexandre Courbot <acourbot@nvidia.com>
Signed-off-by: Alexandre Courbot <acourbot@nvidia.com>
Message-ID: <20251110-gsp_boot-v9-5-8ae4058e3c0e@nvidia.com>

authored by

Alistair Popple and committed by
Alexandre Courbot
41235c40 f38b4f10

+73 -7
-1
drivers/gpu/nova-core/fb.rs
··· 98 98 /// 99 99 /// Contains ranges of GPU memory reserved for a given purpose during the GSP boot process. 100 100 #[derive(Debug)] 101 - #[expect(dead_code)] 102 101 pub(crate) struct FbLayout { 103 102 /// Range of the framebuffer. Starts at `0`. 104 103 pub(crate) fb: Range<u64>,
+1 -2
drivers/gpu/nova-core/firmware/gsp.rs
··· 145 145 /// Size in bytes of the firmware contained in [`Self::fw`]. 146 146 pub(crate) size: usize, 147 147 /// Device-mapped GSP signatures matching the GPU's [`Chipset`]. 148 - signatures: DmaObject, 148 + pub(crate) signatures: DmaObject, 149 149 /// GSP bootloader, verifies the GSP firmware before loading and running it. 150 150 pub(crate) bootloader: RiscvFirmware, 151 151 } ··· 231 231 })) 232 232 } 233 233 234 - #[expect(unused)] 235 234 /// Returns the DMA handle of the radix3 level 0 page table. 236 235 pub(crate) fn radix3_dma_handle(&self) -> DmaAddress { 237 236 self.level0.dma_handle()
+3 -3
drivers/gpu/nova-core/firmware/riscv.rs
··· 60 60 #[expect(unused)] 61 61 pub(crate) struct RiscvFirmware { 62 62 /// Offset at which the code starts in the firmware image. 63 - code_offset: u32, 63 + pub(crate) code_offset: u32, 64 64 /// Offset at which the data starts in the firmware image. 65 - data_offset: u32, 65 + pub(crate) data_offset: u32, 66 66 /// Offset at which the manifest starts in the firmware image. 67 - manifest_offset: u32, 67 + pub(crate) manifest_offset: u32, 68 68 /// Application version. 69 69 app_version: u32, 70 70 /// Device-mapped firmware image.
+7
drivers/gpu/nova-core/gsp/boot.rs
··· 2 2 3 3 use kernel::{ 4 4 device, 5 + dma::CoherentAllocation, 6 + dma_write, 5 7 pci, 6 8 prelude::*, // 7 9 }; ··· 29 27 FIRMWARE_VERSION, // 30 28 }, 31 29 gpu::Chipset, 30 + gsp::GspFwWprMeta, 32 31 regs, 33 32 vbios::Vbios, 34 33 }; ··· 148 145 sec2_falcon, 149 146 bar, 150 147 )?; 148 + 149 + let wpr_meta = 150 + CoherentAllocation::<GspFwWprMeta>::alloc_coherent(dev, 1, GFP_KERNEL | __GFP_ZERO)?; 151 + dma_write!(wpr_meta[0] = GspFwWprMeta::new(&gsp_fw, &fb_layout))?; 151 152 152 153 Ok(()) 153 154 }
+60 -1
drivers/gpu/nova-core/gsp/fw.rs
··· 13 13 Alignable, 14 14 Alignment, // 15 15 }, 16 - sizes::SZ_1M, 16 + sizes::{ 17 + SZ_128K, 18 + SZ_1M, // 19 + }, 17 20 transmute::{ 18 21 AsBytes, 19 22 FromBytes, // ··· 24 21 }; 25 22 26 23 use crate::{ 24 + fb::FbLayout, 25 + firmware::gsp::GspFirmware, 27 26 gpu::Chipset, 28 27 num::{ 29 28 self, ··· 126 121 /// addresses of the GSP bootloader and firmware. 127 122 #[repr(transparent)] 128 123 pub(crate) struct GspFwWprMeta(bindings::GspFwWprMeta); 124 + 125 + // SAFETY: Padding is explicit and does not contain uninitialized data. 126 + unsafe impl AsBytes for GspFwWprMeta {} 127 + 128 + // SAFETY: This struct only contains integer types for which all bit patterns 129 + // are valid. 130 + unsafe impl FromBytes for GspFwWprMeta {} 131 + 132 + type GspFwWprMetaBootResumeInfo = r570_144::GspFwWprMeta__bindgen_ty_1; 133 + type GspFwWprMetaBootInfo = r570_144::GspFwWprMeta__bindgen_ty_1__bindgen_ty_1; 134 + 135 + impl GspFwWprMeta { 136 + /// Fill in and return a `GspFwWprMeta` suitable for booting `gsp_firmware` using the 137 + /// `fb_layout` layout. 138 + pub(crate) fn new(gsp_firmware: &GspFirmware, fb_layout: &FbLayout) -> Self { 139 + Self(bindings::GspFwWprMeta { 140 + // CAST: we want to store the bits of `GSP_FW_WPR_META_MAGIC` unmodified. 141 + magic: r570_144::GSP_FW_WPR_META_MAGIC as u64, 142 + revision: u64::from(r570_144::GSP_FW_WPR_META_REVISION), 143 + sysmemAddrOfRadix3Elf: gsp_firmware.radix3_dma_handle(), 144 + sizeOfRadix3Elf: u64::from_safe_cast(gsp_firmware.size), 145 + sysmemAddrOfBootloader: gsp_firmware.bootloader.ucode.dma_handle(), 146 + sizeOfBootloader: u64::from_safe_cast(gsp_firmware.bootloader.ucode.size()), 147 + bootloaderCodeOffset: u64::from(gsp_firmware.bootloader.code_offset), 148 + bootloaderDataOffset: u64::from(gsp_firmware.bootloader.data_offset), 149 + bootloaderManifestOffset: u64::from(gsp_firmware.bootloader.manifest_offset), 150 + __bindgen_anon_1: GspFwWprMetaBootResumeInfo { 151 + __bindgen_anon_1: GspFwWprMetaBootInfo { 152 + sysmemAddrOfSignature: gsp_firmware.signatures.dma_handle(), 153 + sizeOfSignature: u64::from_safe_cast(gsp_firmware.signatures.size()), 154 + }, 155 + }, 156 + gspFwRsvdStart: fb_layout.heap.start, 157 + nonWprHeapOffset: fb_layout.heap.start, 158 + nonWprHeapSize: fb_layout.heap.end - fb_layout.heap.start, 159 + gspFwWprStart: fb_layout.wpr2.start, 160 + gspFwHeapOffset: fb_layout.wpr2_heap.start, 161 + gspFwHeapSize: fb_layout.wpr2_heap.end - fb_layout.wpr2_heap.start, 162 + gspFwOffset: fb_layout.elf.start, 163 + bootBinOffset: fb_layout.boot.start, 164 + frtsOffset: fb_layout.frts.start, 165 + frtsSize: fb_layout.frts.end - fb_layout.frts.start, 166 + gspFwWprEnd: fb_layout 167 + .vga_workspace 168 + .start 169 + .align_down(Alignment::new::<SZ_128K>()), 170 + gspFwHeapVfPartitionCount: fb_layout.vf_partition_count, 171 + fbSize: fb_layout.fb.end - fb_layout.fb.start, 172 + vgaWorkspaceOffset: fb_layout.vga_workspace.start, 173 + vgaWorkspaceSize: fb_layout.vga_workspace.end - fb_layout.vga_workspace.start, 174 + ..Default::default() 175 + }) 176 + } 177 + } 129 178 130 179 /// Struct containing the arguments required to pass a memory buffer to the GSP 131 180 /// for use during initialisation.
+2
drivers/gpu/nova-core/gsp/fw/r570_144/bindings.rs
··· 9 9 pub const GSP_FW_HEAP_SIZE_OVERRIDE_LIBOS2_MAX_MB: u32 = 256; 10 10 pub const GSP_FW_HEAP_SIZE_OVERRIDE_LIBOS3_BAREMETAL_MIN_MB: u32 = 88; 11 11 pub const GSP_FW_HEAP_SIZE_OVERRIDE_LIBOS3_BAREMETAL_MAX_MB: u32 = 280; 12 + pub const GSP_FW_WPR_META_REVISION: u32 = 1; 13 + pub const GSP_FW_WPR_META_MAGIC: i64 = -2577556379034558285; 12 14 pub type __u8 = ffi::c_uchar; 13 15 pub type __u16 = ffi::c_ushort; 14 16 pub type __u32 = ffi::c_uint;