// TODO // // The resulting strings are used to generate firmware paths, hence the // generated strings have to be stable. // // Hence, replace with something like strum_macros derive(Display). // // For now, redirect to fmt::Debug for convenience. impl fmt::Display for Chipset { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{self:?}")
}
}
/// Enum representation of the GPU generation. #[derive(fmt::Debug)] pub(crate) enum Architecture {
Turing = 0x16,
Ampere = 0x17,
Ada = 0x19,
}
impl TryFrom<u8> for Architecture { type Error = Error;
/// Structure holding the resources required to operate the GPU. #[pin_data(PinnedDrop)] pub(crate) struct Gpu {
spec: Spec, /// MMIO mapping of PCI BAR 0
bar: Arc<Devres<Bar0>>,
fw: Firmware, /// System memory page required for flushing all pending GPU-side memory writes done through /// PCIE into system memory, via sysmembar (A GPU-initiated HW memory-barrier operation).
sysmem_flush: SysmemFlush,
}
#[pinned_drop] impl PinnedDrop for Gpu { fn drop(self: Pin<&mutSelf>) { // Unregister the sysmem flush page before we release it. self.bar
.try_access_with(|b| self.sysmem_flush.unregister(b));
}
}
impl Gpu { /// Helper function to load and run the FWSEC-FRTS firmware and confirm that it has properly /// created the WPR2 region. /// /// TODO: this needs to be moved into a larger type responsible for booting the whole GSP /// (`GspBooter`?). fn run_fwsec_frts(
dev: &device::Device<device::Bound>,
falcon: &Falcon<Gsp>,
bar: &Bar0,
bios: &Vbios,
fb_layout: &FbLayout,
) -> Result<()> { // Check that the WPR2 region does not already exists - if it does, we cannot run // FWSEC-FRTS until the GPU is reset. if regs::NV_PFB_PRI_MMU_WPR2_ADDR_HI::read(bar).higher_bound() != 0 {
dev_err!(
dev, "WPR2 region already exists - GPU needs to be reset to proceed\n"
); return Err(EBUSY);
}
let fwsec_frts = FwsecFirmware::new(
dev,
falcon,
bar,
bios,
FwsecCommand::Frts {
frts_addr: fb_layout.frts.start,
frts_size: fb_layout.frts.end - fb_layout.frts.start,
},
)?;
// Run FWSEC-FRTS to create the WPR2 region.
fwsec_frts.run(dev, falcon, bar)?;
// SCRATCH_E contains the error code for FWSEC-FRTS. let frts_status = regs::NV_PBUS_SW_SCRATCH_0E::read(bar).frts_err_code(); if frts_status != 0 {
dev_err!(
dev, "FWSEC-FRTS returned with error code {:#x}",
frts_status
);
return Err(EIO);
}
// Check that the WPR2 region has been created as we requested. let (wpr2_lo, wpr2_hi) = (
regs::NV_PFB_PRI_MMU_WPR2_ADDR_LO::read(bar).lower_bound(),
regs::NV_PFB_PRI_MMU_WPR2_ADDR_HI::read(bar).higher_bound(),
);
match (wpr2_lo, wpr2_hi) {
(_, 0) => {
dev_err!(dev, "WPR2 region not created after running FWSEC-FRTS\n");
Err(EIO)
}
(wpr2_lo, _) if wpr2_lo != fb_layout.frts.start => {
dev_err!(
dev, "WPR2 region created at unexpected address {:#x}; expected {:#x}\n",
wpr2_lo,
fb_layout.frts.start,
);
// We must wait for GFW_BOOT completion before doing any significant setup on the GPU.
gfw::wait_gfw_boot_completion(bar)
.inspect_err(|_| dev_err!(pdev.as_ref(), "GFW boot did not complete"))?;
let sysmem_flush = SysmemFlush::register(pdev.as_ref(), bar, spec.chipset)?;
let gsp_falcon = Falcon::<Gsp>::new(
pdev.as_ref(),
spec.chipset,
bar,
spec.chipset > Chipset::GA100,
)?;
gsp_falcon.clear_swgen0_intr(bar);
let _sec2_falcon = Falcon::<Sec2>::new(pdev.as_ref(), spec.chipset, bar, true)?;
let fb_layout = FbLayout::new(spec.chipset, bar)?;
dev_dbg!(pdev.as_ref(), "{:#x?}\n", fb_layout);
let bios = Vbios::new(pdev, bar)?;
Self::run_fwsec_frts(pdev.as_ref(), &gsp_falcon, bar, &bios, &fb_layout)?;
Ok(pin_init!(Self {
spec,
bar: devres_bar,
fw,
sysmem_flush,
}))
}
}
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.14 Sekunden
(vorverarbeitet am 2026-06-19)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.