1 // SPDX-License-Identifier: GPL-2.0 2 3 use kernel::{ 4 device, 5 dma::Coherent, 6 io::poll::read_poll_timeout, 7 io::Io, 8 pci, 9 prelude::*, 10 time::Delta, // 11 }; 12 13 use crate::{ 14 driver::Bar0, 15 falcon::{ 16 gsp::Gsp, 17 sec2::Sec2, 18 Falcon, // 19 }, 20 fb::FbLayout, 21 firmware::{ 22 booter::{ 23 BooterFirmware, 24 BooterKind, // 25 }, 26 fwsec::{ 27 bootloader::FwsecFirmwareWithBl, 28 FwsecCommand, 29 FwsecFirmware, // 30 }, 31 gsp::GspFirmware, 32 FIRMWARE_VERSION, // 33 }, 34 gpu::{ 35 Architecture, 36 Chipset, // 37 }, 38 gsp::{ 39 commands, 40 sequencer::{ 41 GspSequencer, 42 GspSequencerParams, // 43 }, 44 GspFwWprMeta, // 45 }, 46 regs, 47 vbios::Vbios, 48 }; 49 50 impl super::Gsp { 51 /// Helper function to load and run the FWSEC-FRTS firmware and confirm that it has properly 52 /// created the WPR2 region. 53 fn run_fwsec_frts( 54 dev: &device::Device<device::Bound>, 55 chipset: Chipset, 56 falcon: &Falcon<Gsp>, 57 bar: &Bar0, 58 bios: &Vbios, 59 fb_layout: &FbLayout, 60 ) -> Result<()> { 61 // Check that the WPR2 region does not already exists - if it does, we cannot run 62 // FWSEC-FRTS until the GPU is reset. 63 if bar.read(regs::NV_PFB_PRI_MMU_WPR2_ADDR_HI).higher_bound() != 0 { 64 dev_err!( 65 dev, 66 "WPR2 region already exists - GPU needs to be reset to proceed\n" 67 ); 68 return Err(EBUSY); 69 } 70 71 // FWSEC-FRTS will create the WPR2 region. 72 let fwsec_frts = FwsecFirmware::new( 73 dev, 74 falcon, 75 bar, 76 bios, 77 FwsecCommand::Frts { 78 frts_addr: fb_layout.frts.start, 79 frts_size: fb_layout.frts.len(), 80 }, 81 )?; 82 83 if chipset.needs_fwsec_bootloader() { 84 let fwsec_frts_bl = FwsecFirmwareWithBl::new(fwsec_frts, dev, chipset)?; 85 // Load and run the bootloader, which will load FWSEC-FRTS and run it. 86 fwsec_frts_bl.run(dev, falcon, bar)?; 87 } else { 88 // Load and run FWSEC-FRTS directly. 89 fwsec_frts.run(dev, falcon, bar)?; 90 } 91 92 // SCRATCH_E contains the error code for FWSEC-FRTS. 93 let frts_status = bar 94 .read(regs::NV_PBUS_SW_SCRATCH_0E_FRTS_ERR) 95 .frts_err_code(); 96 if frts_status != 0 { 97 dev_err!( 98 dev, 99 "FWSEC-FRTS returned with error code {:#x}\n", 100 frts_status 101 ); 102 103 return Err(EIO); 104 } 105 106 // Check that the WPR2 region has been created as we requested. 107 let (wpr2_lo, wpr2_hi) = ( 108 bar.read(regs::NV_PFB_PRI_MMU_WPR2_ADDR_LO).lower_bound(), 109 bar.read(regs::NV_PFB_PRI_MMU_WPR2_ADDR_HI).higher_bound(), 110 ); 111 112 match (wpr2_lo, wpr2_hi) { 113 (_, 0) => { 114 dev_err!(dev, "WPR2 region not created after running FWSEC-FRTS\n"); 115 116 Err(EIO) 117 } 118 (wpr2_lo, _) if wpr2_lo != fb_layout.frts.start => { 119 dev_err!( 120 dev, 121 "WPR2 region created at unexpected address {:#x}; expected {:#x}\n", 122 wpr2_lo, 123 fb_layout.frts.start, 124 ); 125 126 Err(EIO) 127 } 128 (wpr2_lo, wpr2_hi) => { 129 dev_dbg!(dev, "WPR2: {:#x}-{:#x}\n", wpr2_lo, wpr2_hi); 130 dev_dbg!(dev, "GPU instance built\n"); 131 132 Ok(()) 133 } 134 } 135 } 136 137 /// Attempt to boot the GSP. 138 /// 139 /// This is a GPU-dependent and complex procedure that involves loading firmware files from 140 /// user-space, patching them with signatures, and building firmware-specific intricate data 141 /// structures that the GSP will use at runtime. 142 /// 143 /// Upon return, the GSP is up and running, and its runtime object given as return value. 144 pub(crate) fn boot( 145 self: Pin<&mut Self>, 146 pdev: &pci::Device<device::Bound>, 147 bar: &Bar0, 148 chipset: Chipset, 149 gsp_falcon: &Falcon<Gsp>, 150 sec2_falcon: &Falcon<Sec2>, 151 ) -> Result { 152 // The FSP boot process of Hopper+ is not supported for now. 153 if matches!( 154 chipset.arch(), 155 Architecture::Hopper | Architecture::BlackwellGB10x | Architecture::BlackwellGB20x 156 ) { 157 return Err(ENOTSUPP); 158 } 159 160 let dev = pdev.as_ref(); 161 162 let bios = Vbios::new(dev, bar)?; 163 164 let gsp_fw = KBox::pin_init(GspFirmware::new(dev, chipset, FIRMWARE_VERSION), GFP_KERNEL)?; 165 166 let fb_layout = FbLayout::new(chipset, bar, &gsp_fw)?; 167 dev_dbg!(dev, "{:#x?}\n", fb_layout); 168 169 // FWSEC-FRTS is not executed on chips where the FRTS region size is 0 (e.g. GA100). 170 if !fb_layout.frts.is_empty() { 171 Self::run_fwsec_frts(dev, chipset, gsp_falcon, bar, &bios, &fb_layout)?; 172 } 173 174 let booter_loader = BooterFirmware::new( 175 dev, 176 BooterKind::Loader, 177 chipset, 178 FIRMWARE_VERSION, 179 sec2_falcon, 180 bar, 181 )?; 182 183 let wpr_meta = Coherent::init(dev, GFP_KERNEL, GspFwWprMeta::new(&gsp_fw, &fb_layout))?; 184 185 self.cmdq 186 .send_command_no_wait(bar, commands::SetSystemInfo::new(pdev))?; 187 self.cmdq 188 .send_command_no_wait(bar, commands::SetRegistry::new())?; 189 190 gsp_falcon.reset(bar)?; 191 let libos_handle = self.libos.dma_handle(); 192 let (mbox0, mbox1) = gsp_falcon.boot( 193 bar, 194 Some(libos_handle as u32), 195 Some((libos_handle >> 32) as u32), 196 )?; 197 dev_dbg!(pdev, "GSP MBOX0: {:#x}, MBOX1: {:#x}\n", mbox0, mbox1); 198 199 dev_dbg!( 200 pdev, 201 "Using SEC2 to load and run the booter_load firmware...\n" 202 ); 203 204 sec2_falcon.reset(bar)?; 205 sec2_falcon.load(dev, bar, &booter_loader)?; 206 let wpr_handle = wpr_meta.dma_handle(); 207 let (mbox0, mbox1) = sec2_falcon.boot( 208 bar, 209 Some(wpr_handle as u32), 210 Some((wpr_handle >> 32) as u32), 211 )?; 212 dev_dbg!(pdev, "SEC2 MBOX0: {:#x}, MBOX1: {:#x}\n", mbox0, mbox1); 213 214 if mbox0 != 0 { 215 dev_err!(pdev, "Booter-load failed with error {:#x}\n", mbox0); 216 return Err(ENODEV); 217 } 218 219 gsp_falcon.write_os_version(bar, gsp_fw.bootloader.app_version); 220 221 // Poll for RISC-V to become active before running sequencer 222 read_poll_timeout( 223 || Ok(gsp_falcon.is_riscv_active(bar)), 224 |val: &bool| *val, 225 Delta::from_millis(10), 226 Delta::from_secs(5), 227 )?; 228 229 dev_dbg!(pdev, "RISC-V active? {}\n", gsp_falcon.is_riscv_active(bar),); 230 231 // Create and run the GSP sequencer. 232 let seq_params = GspSequencerParams { 233 bootloader_app_version: gsp_fw.bootloader.app_version, 234 libos_dma_handle: libos_handle, 235 gsp_falcon, 236 sec2_falcon, 237 dev: pdev.as_ref().into(), 238 bar, 239 }; 240 GspSequencer::run(&self.cmdq, seq_params)?; 241 242 // Wait until GSP is fully initialized. 243 commands::wait_gsp_init_done(&self.cmdq)?; 244 245 // Obtain and display basic GPU information. 246 let info = commands::get_gsp_info(&self.cmdq, bar)?; 247 match info.gpu_name() { 248 Ok(name) => dev_info!(pdev, "GPU name: {}\n", name), 249 Err(e) => dev_warn!(pdev, "GPU name unavailable: {:?}\n", e), 250 } 251 252 Ok(()) 253 } 254 } 255