drivers/gpu/nova-core/firmware/gsp.rs

Source file repositories/reference/linux-study-clean/drivers/gpu/nova-core/firmware/gsp.rs

File Facts

System
Linux kernel
Corpus path
drivers/gpu/nova-core/firmware/gsp.rs
Extension
.rs
Size
7177 bytes
Lines
189
Domain
Driver Families
Bucket
drivers/gpu
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

// SPDX-License-Identifier: GPL-2.0

use kernel::{
    device,
    dma::{
        Coherent,
        CoherentBox,
        DataDirection,
        DmaAddress, //
    },
    prelude::*,
    scatterlist::{
        Owned,
        SGTable, //
    },
};

use crate::{
    firmware::{
        elf,
        riscv::RiscvFirmware, //
    },
    gpu::{
        Architecture,
        Chipset, //
    },
    gsp::GSP_PAGE_SIZE,
    num::FromSafeCast,
};

/// GSP firmware with 3-level radix page tables for the GSP bootloader.
///
/// The bootloader expects firmware to be mapped starting at address 0 in GSP's virtual address
/// space:
///
/// ```text
/// Level 0:  1 page, 1 entry         -> points to first level 1 page
/// Level 1:  Multiple pages/entries  -> each entry points to a level 2 page
/// Level 2:  Multiple pages/entries  -> each entry points to a firmware page
/// ```
///
/// Each page is 4KB, each entry is 8 bytes (64-bit DMA address).
/// Also known as "Radix3" firmware.
#[pin_data]
pub(crate) struct GspFirmware {
    /// The GSP firmware inside a [`VVec`], device-mapped via a SG table.
    #[pin]
    fw: SGTable<Owned<VVec<u8>>>,
    /// Level 2 page table whose entries contain DMA addresses of firmware pages.
    #[pin]
    level2: SGTable<Owned<VVec<u8>>>,
    /// Level 1 page table whose entries contain DMA addresses of level 2 pages.
    #[pin]
    level1: SGTable<Owned<VVec<u8>>>,
    /// Level 0 page table (single 4KB page) with one entry: DMA address of first level 1 page.
    level0: Coherent<[u64]>,
    /// Size in bytes of the firmware contained in [`Self::fw`].
    pub(crate) size: usize,
    /// Device-mapped GSP signatures matching the GPU's [`Chipset`].
    pub(crate) signatures: Coherent<[u8]>,
    /// GSP bootloader, verifies the GSP firmware before loading and running it.
    pub(crate) bootloader: RiscvFirmware,
}

impl GspFirmware {
    fn find_gsp_sigs_section(chipset: Chipset) -> &'static str {
        match chipset.arch() {
            Architecture::Turing if matches!(chipset, Chipset::TU116 | Chipset::TU117) => {
                ".fwsignature_tu11x"
            }
            Architecture::Turing => ".fwsignature_tu10x",
            Architecture::Ampere if chipset == Chipset::GA100 => ".fwsignature_ga100",
            Architecture::Ampere => ".fwsignature_ga10x",
            Architecture::Ada => ".fwsignature_ad10x",
            Architecture::Hopper => ".fwsignature_gh10x",
            Architecture::BlackwellGB10x => ".fwsignature_gb10x",
            Architecture::BlackwellGB20x => ".fwsignature_gb20x",
        }
    }

    /// Loads the GSP firmware binaries, map them into `dev`'s address-space, and creates the page
    /// tables expected by the GSP bootloader to load it.
    pub(crate) fn new<'a>(
        dev: &'a device::Device<device::Bound>,
        chipset: Chipset,
        ver: &'a str,
    ) -> impl PinInit<Self, Error> + 'a {
        pin_init::pin_init_scope(move || {
            let firmware = super::request_firmware(dev, chipset, "gsp", ver)?;

Annotation

Implementation Notes