1 /* 2 * SPDX-FileCopyrightText: Copyright (c) 2021-2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 3 * SPDX-License-Identifier: MIT 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the "Software"), 7 * to deal in the Software without restriction, including without limitation 8 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 * and/or sell copies of the Software, and to permit persons to whom the 10 * Software is furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice shall be included in 13 * all copies or substantial portions of the Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 * DEALINGS IN THE SOFTWARE. 22 */ 23 24 /*! 25 * Provides GH100+ specific KernelGsp HAL implementations. 26 */ 27 28 #include "rmconfig.h" 29 #include "gpu/conf_compute/conf_compute.h" 30 #include "gpu/fsp/kern_fsp.h" 31 #include "gpu/gsp/kernel_gsp.h" 32 #include "gpu/mem_sys/kern_mem_sys.h" 33 #include "gsp/gspifpub.h" 34 #include "vgpu/rpc.h" 35 36 #include "published/hopper/gh100/dev_falcon_v4.h" 37 #include "published/hopper/gh100/dev_gsp.h" 38 #include "published/hopper/gh100/dev_riscv_pri.h" 39 40 #define RISCV_BR_ADDR_ALIGNMENT (8) 41 42 const char* 43 kgspGetSignatureSectionNamePrefix_GH100 44 ( 45 OBJGPU *pGpu, 46 KernelGsp *pKernelGsp 47 ) 48 { 49 ConfidentialCompute *pCC = GPU_GET_CONF_COMPUTE(pGpu); 50 if (pCC != NULL && pCC->getProperty(pCC, PDB_PROP_CONFCOMPUTE_CC_FEATURE_ENABLED)) 51 return GSP_CC_SIGNATURE_SECTION_NAME_PREFIX; 52 return GSP_SIGNATURE_SECTION_NAME_PREFIX; 53 } 54 55 56 /*! 57 * Helper Function for kgspResetHw_GH100 58 * 59 * @param[in] pGpu OBJGPU pointer 60 * @param[in] pVoid unused void pointer 61 * 62 * @return NvBool NV_TRUE if reset FSM reports ASSERTED 63 */ 64 static NvBool 65 _kgspWaitForAsserted 66 ( 67 OBJGPU *pGpu, 68 void *pVoid 69 ) 70 { 71 return GPU_FLD_TEST_DRF_DEF(pGpu, _PGSP, _FALCON_ENGINE, _RESET_STATUS, 72 _ASSERTED); 73 } 74 75 76 /*! 77 * Helper Function for kgspResetHw_GH100 78 * 79 * @param[in] pGpu OBJGPU pointer 80 * @param[in] pVoid unused void pointer 81 * 82 * @return NvBool NV_TRUE if reset FSM reports DEASSERTED 83 */ 84 static NvBool 85 _kgspWaitForDeasserted 86 ( 87 OBJGPU *pGpu, 88 void *pVoid 89 ) 90 { 91 return GPU_FLD_TEST_DRF_DEF(pGpu, _PGSP, _FALCON_ENGINE, _RESET_STATUS, 92 _DEASSERTED); 93 } 94 95 /*! 96 * Reset the GSP HW 97 * 98 * @return NV_OK if the GSP HW was properly reset 99 */ 100 NV_STATUS 101 kgspResetHw_GH100 102 ( 103 OBJGPU *pGpu, 104 KernelGsp *pKernelGsp 105 ) 106 { 107 NV_STATUS status = NV_OK; 108 RMTIMEOUT timeout; 109 110 // 111 // Add a delay for 10us. This is a worst case estimate. 112 // See bug 200636529 comment 20 113 // Use PTIMER instead of the default ostimer since it is much faster than the 114 // former and hence does not cause sufficient delay. 115 // 116 gpuSetTimeout(pGpu, 10, &timeout, GPU_TIMEOUT_FLAGS_TMR); 117 118 GPU_FLD_WR_DRF_DEF(pGpu, _PGSP, _FALCON_ENGINE, _RESET, _ASSERT); 119 status = gpuTimeoutCondWait(pGpu, _kgspWaitForAsserted, NULL, &timeout); 120 if (status != NV_OK) 121 { 122 NV_PRINTF(LEVEL_ERROR, "Timed out waiting for GSP falcon reset to assert\n"); 123 DBG_BREAKPOINT(); 124 } 125 126 // Reset timeout 127 gpuSetTimeout(pGpu, 10, &timeout, GPU_TIMEOUT_FLAGS_TMR); 128 129 GPU_FLD_WR_DRF_DEF(pGpu, _PGSP, _FALCON_ENGINE, _RESET, _DEASSERT); 130 status = gpuTimeoutCondWait(pGpu, _kgspWaitForDeasserted, NULL, &timeout); 131 if (status != NV_OK) 132 { 133 NV_PRINTF(LEVEL_ERROR, "Timed out waiting for GSP falcon reset to deassert\n"); 134 DBG_BREAKPOINT(); 135 } 136 137 return status; 138 } 139 140 NV_STATUS 141 kgspAllocBootArgs_GH100 142 ( 143 OBJGPU *pGpu, 144 KernelGsp *pKernelGsp 145 ) 146 { 147 NvP64 pVa = NvP64_NULL; 148 NvP64 pPriv = NvP64_NULL; 149 NV_STATUS nvStatus = NV_OK; 150 NvU64 flags = MEMDESC_FLAGS_NONE; 151 152 flags |= MEMDESC_FLAGS_ALLOC_IN_UNPROTECTED_MEMORY; 153 154 // Allocate GSP-FMC arguments 155 NV_ASSERT_OK_OR_GOTO(nvStatus, 156 memdescCreate(&pKernelGsp->pGspFmcArgumentsDescriptor, 157 pGpu, sizeof(GSP_FMC_BOOT_PARAMS), 0x1000, 158 NV_TRUE, ADDR_SYSMEM, NV_MEMORY_CACHED, 159 flags), 160 _kgspAllocBootArgs_exit_cleanup); 161 162 NV_ASSERT_OK_OR_GOTO(nvStatus, 163 memdescAlloc(pKernelGsp->pGspFmcArgumentsDescriptor), 164 _kgspAllocBootArgs_exit_cleanup); 165 166 NV_ASSERT_OK_OR_GOTO(nvStatus, 167 memdescMap(pKernelGsp->pGspFmcArgumentsDescriptor, 0, 168 memdescGetSize(pKernelGsp->pGspFmcArgumentsDescriptor), 169 NV_TRUE, NV_PROTECT_READ_WRITE, 170 &pVa, &pPriv), 171 _kgspAllocBootArgs_exit_cleanup); 172 173 pKernelGsp->pGspFmcArgumentsCached = (GSP_FMC_BOOT_PARAMS *)NvP64_VALUE(pVa); 174 pKernelGsp->pGspFmcArgumentsMappingPriv = pPriv; 175 176 return kgspAllocBootArgs_TU102(pGpu, pKernelGsp); 177 178 _kgspAllocBootArgs_exit_cleanup: 179 kgspFreeBootArgs_HAL(pGpu, pKernelGsp); 180 return nvStatus; 181 } 182 183 void 184 kgspFreeBootArgs_GH100 185 ( 186 OBJGPU *pGpu, 187 KernelGsp *pKernelGsp 188 ) 189 { 190 kgspFreeBootArgs_TU102(pGpu, pKernelGsp); 191 192 // release wpr meta data resources 193 if (pKernelGsp->pGspFmcArgumentsCached != NULL) 194 { 195 memdescUnmap(pKernelGsp->pGspFmcArgumentsDescriptor, 196 NV_TRUE, osGetCurrentProcess(), 197 (void *)pKernelGsp->pGspFmcArgumentsCached, 198 pKernelGsp->pGspFmcArgumentsMappingPriv); 199 pKernelGsp->pGspFmcArgumentsCached = NULL; 200 pKernelGsp->pGspFmcArgumentsMappingPriv = NULL; 201 } 202 if (pKernelGsp->pGspFmcArgumentsDescriptor != NULL) 203 { 204 memdescFree(pKernelGsp->pGspFmcArgumentsDescriptor); 205 memdescDestroy(pKernelGsp->pGspFmcArgumentsDescriptor); 206 pKernelGsp->pGspFmcArgumentsDescriptor = NULL; 207 } 208 } 209 210 NvBool 211 kgspIsWpr2Up_GH100 212 ( 213 OBJGPU *pGpu, 214 KernelGsp *pKernelGsp 215 ) 216 { 217 ConfidentialCompute *pCC = GPU_GET_CONF_COMPUTE(pGpu); 218 if (pCC != NULL && pCC->getProperty(pCC, PDB_PROP_CONFCOMPUTE_CC_FEATURE_ENABLED)) 219 { 220 // 221 // Due to BAR0 decoupler, we may not be able to read WPR2 MMU regs. 222 // Assume WPR2 is down. 223 // 224 return NV_FALSE; 225 } 226 227 return kgspIsWpr2Up_TU102(pGpu, pKernelGsp); 228 } 229 230 NV_STATUS 231 kgspWaitForGfwBootOk_GH100 232 ( 233 OBJGPU *pGpu, 234 KernelGsp *pKernelGsp 235 ) 236 { 237 KernelFsp *pKernelFsp = GPU_GET_KERNEL_FSP(pGpu); 238 239 if (pKernelFsp != NULL) 240 { 241 return kfspWaitForSecureBoot_HAL(pGpu, pKernelFsp); 242 } 243 244 return NV_OK; 245 } 246 247 /*! 248 * Calculate the FB layout. On Hopper, this consists of determining the 249 * minimum sizes of various regions that Client RM provides as inputs. 250 * The actual offsets are determined by secure ACR ucode and patched 251 * into the GspFwWprMeta structure provided to GSP-RM, so most of the 252 * structure is 0-initialized here. 253 * 254 * Firmware scrubs the last 256mb of FB, no memory outside of this region 255 * may be used until the FW RM has scrubbed the remainder of memory. 256 * 257 * ---------------------------- <- fbSize (end of FB, 1M aligned) 258 * | VGA WORKSPACE | 259 * ---------------------------- <- vbiosReservedOffset (64K? aligned) 260 * | (potential align. gap) | 261 * ---------------------------- <- gspFwWprEnd (128K aligned) 262 * | FRTS data | 263 * | ------------------------ | <- frtsOffset 264 * | BOOT BIN (e.g. GSP-FMC) | 265 * ---------------------------- <- bootBinOffset 266 * | GSP FW ELF | 267 * ---------------------------- <- gspFwOffset 268 * | GSP FW (WPR) HEAP | 269 * ---------------------------- <- gspFwHeapOffset 270 * | ACR-placed metadata | 271 * | (struct GspFwWprMeta) | 272 * ---------------------------- <- gspFwWprStart (128K aligned) 273 * | GSP FW (non-WPR) HEAP | 274 * ---------------------------- <- nonWprHeapOffset, gspFwRsvdStart 275 * 276 * @param pGpu GPU object pointer 277 * @param pKernelGsp KernelGsp object pointer 278 * @param pGspFw Pointer to GSP-RM fw image. 279 * @param pFbRegionInfo Pointer to fb region table to fill in. 280 */ 281 NV_STATUS 282 kgspCalculateFbLayout_GH100 283 ( 284 OBJGPU *pGpu, 285 KernelGsp *pKernelGsp, 286 GSP_FIRMWARE *pGspFw 287 ) 288 { 289 GspFwWprMeta *pWprMeta = pKernelGsp->pWprMeta; 290 RM_RISCV_UCODE_DESC *pRiscvDesc = pKernelGsp->pGspRmBootUcodeDesc; 291 292 ct_assert(sizeof(*pWprMeta) == 256); 293 294 NV_ASSERT_OR_RETURN(IS_GSP_CLIENT(pGpu), NV_ERR_NOT_SUPPORTED); 295 296 NV_ASSERT_OR_RETURN(pKernelGsp->pGspRmBootUcodeImage != NULL, NV_ERR_INVALID_STATE); 297 NV_ASSERT_OR_RETURN(pKernelGsp->gspRmBootUcodeSize != 0, NV_ERR_INVALID_STATE); 298 NV_ASSERT_OR_RETURN(pRiscvDesc != NULL, NV_ERR_INVALID_STATE); 299 300 portMemSet(pWprMeta, 0, sizeof *pWprMeta); 301 302 // 303 // We send this to FSP as the size to reserve above FRTS. 304 // The actual offset gets filled in by ACR ucode when it sets up WPR2. 305 // 306 pWprMeta->vgaWorkspaceSize = 128 * 1024; 307 308 // Physical address and size of GSP-FMC ucode in system memory 309 pWprMeta->sizeOfBootloader = pKernelGsp->gspRmBootUcodeSize; 310 pWprMeta->sysmemAddrOfBootloader = 311 memdescGetPhysAddr(pKernelGsp->pGspRmBootUcodeMemdesc, AT_GPU, 0); 312 313 // Physical address and size of GSP-RM firmware in system memory 314 pWprMeta->sizeOfRadix3Elf = pGspFw->imageSize; 315 pWprMeta->sysmemAddrOfRadix3Elf = 316 memdescGetPhysAddr(pKernelGsp->pGspUCodeRadix3Descriptor, AT_GPU, 0); 317 318 // Set necessary info from the GSP-FMC desc 319 pWprMeta->bootloaderCodeOffset = pRiscvDesc->monitorCodeOffset; 320 pWprMeta->bootloaderDataOffset = pRiscvDesc->monitorDataOffset; 321 pWprMeta->bootloaderManifestOffset = pRiscvDesc->manifestOffset; 322 323 if (pKernelGsp->pSignatureMemdesc != NULL) 324 { 325 pWprMeta->sysmemAddrOfSignature = memdescGetPhysAddr(pKernelGsp->pSignatureMemdesc, AT_GPU, 0); 326 pWprMeta->sizeOfSignature = memdescGetSize(pKernelGsp->pSignatureMemdesc); 327 } 328 329 // The non-WPR heap lives in front of the WPR region 330 pWprMeta->nonWprHeapSize = kgspGetNonWprHeapSize(pGpu, pKernelGsp); 331 332 // 333 // The WPR heap size (gspFwHeapSize) is variable to also get any padding needed 334 // in the carveout to align the WPR start. This is a minimum size request to 335 // the GSP-FMC. 336 // 337 // We won't know the exact size of everything that comes after the heap until 338 // after the GSP-FMC lays it all out during boot. At any rate, this value isn't 339 // needed on Hopper+, since the GSP-FMC can scrub/unlock anything we would need 340 // before GSP-RM boots, so we pass 0 to allow the heap to extend outside the 341 // pre-scrubbed area at the end of FB, if needed. 342 // 343 pWprMeta->gspFwHeapSize = kgspGetFwHeapSize(pGpu, pKernelGsp, 0); 344 345 // Number of VF partitions allocating sub-heaps from the WPR heap 346 pWprMeta->gspFwHeapVfPartitionCount = 347 pGpu->bVgpuGspPluginOffloadEnabled ? MAX_PARTITIONS_WITH_GFID : 0; 348 349 // CrashCat queue (if allocated in sysmem) 350 KernelCrashCatEngine *pKernelCrashCatEng = staticCast(pKernelGsp, KernelCrashCatEngine); 351 MEMORY_DESCRIPTOR *pCrashCatQueueMemDesc = kcrashcatEngineGetQueueMemDesc(pKernelCrashCatEng); 352 if (pCrashCatQueueMemDesc != NULL) 353 { 354 NV_ASSERT_CHECKED(memdescGetAddressSpace(pCrashCatQueueMemDesc) == ADDR_SYSMEM); 355 pWprMeta->sysmemAddrOfCrashReportQueue = memdescGetPhysAddr(pCrashCatQueueMemDesc, AT_GPU, 0); 356 pWprMeta->sizeOfCrashReportQueue = (NvU32)memdescGetSize(pCrashCatQueueMemDesc); 357 } 358 359 // Fill in the meta-metadata 360 pWprMeta->revision = GSP_FW_WPR_META_REVISION; 361 pWprMeta->magic = GSP_FW_WPR_META_MAGIC; 362 363 return NV_OK; 364 } 365 366 static GSP_DMA_TARGET _kgspMemdescToDmaTarget 367 ( 368 MEMORY_DESCRIPTOR *pMemDesc 369 ) 370 { 371 switch (memdescGetAddressSpace(pMemDesc)) 372 { 373 case ADDR_SYSMEM: 374 return (NV_MEMORY_CACHED == memdescGetCpuCacheAttrib(pMemDesc)) ? GSP_DMA_TARGET_COHERENT_SYSTEM 375 : GSP_DMA_TARGET_NONCOHERENT_SYSTEM; 376 case ADDR_FBMEM: 377 return GSP_DMA_TARGET_LOCAL_FB; 378 default: 379 return GSP_DMA_TARGET_COUNT; 380 } 381 } 382 383 /*! 384 * @brief Creates and populates the GSP-FMC/ACR arguments for booting GSP-RM. 385 */ 386 NV_STATUS 387 kgspSetupGspFmcArgs_GH100 388 ( 389 OBJGPU *pGpu, 390 KernelGsp *pKernelGsp, 391 GSP_FIRMWARE *pGspFw 392 ) 393 { 394 NV_ASSERT_OR_RETURN(IS_GSP_CLIENT(pGpu), NV_ERR_NOT_SUPPORTED); 395 NV_ASSERT_OR_RETURN(pKernelGsp->pGspFmcArgumentsCached != NULL, NV_ERR_INVALID_STATE); 396 397 GSP_FMC_BOOT_PARAMS *pGspFmcBootParams = pKernelGsp->pGspFmcArgumentsCached; 398 399 ConfidentialCompute *pCC = GPU_GET_CONF_COMPUTE(pGpu); 400 if (pCC != NULL) 401 { 402 pGspFmcBootParams->initParams.regkeys = pCC->gspProxyRegkeys; 403 } 404 405 pGspFmcBootParams->bootGspRmParams.gspRmDescOffset = memdescGetPhysAddr(pKernelGsp->pWprMetaDescriptor, AT_GPU, 0); 406 pGspFmcBootParams->bootGspRmParams.gspRmDescSize = sizeof(*pKernelGsp->pWprMeta); 407 pGspFmcBootParams->bootGspRmParams.target = _kgspMemdescToDmaTarget(pKernelGsp->pWprMetaDescriptor); 408 pGspFmcBootParams->bootGspRmParams.bIsGspRmBoot = NV_TRUE; 409 410 pGspFmcBootParams->gspRmParams.bootArgsOffset = memdescGetPhysAddr(pKernelGsp->pLibosInitArgumentsDescriptor, AT_GPU, 0); 411 pGspFmcBootParams->gspRmParams.target = _kgspMemdescToDmaTarget(pKernelGsp->pLibosInitArgumentsDescriptor); 412 413 return NV_OK; 414 } 415 416 /*! 417 * Determine if lockdown is released. 418 */ 419 static NvBool 420 _kgspIsLockdownReleased 421 ( 422 OBJGPU *pGpu, 423 void *pVoid 424 ) 425 { 426 KernelGsp *pKernelGsp = reinterpretCast(pVoid, KernelGsp *); 427 NvU32 reg; 428 429 reg = kflcnRegRead_HAL(pGpu, staticCast(pKernelGsp, KernelFalcon), NV_PFALCON_FALCON_HWCFG2); 430 431 return FLD_TEST_DRF(_PFALCON, _FALCON_HWCFG2, _RISCV_BR_PRIV_LOCKDOWN, 432 _UNLOCK, reg); 433 } 434 435 436 437 438 static void 439 _kgspBootstrapGspFmc_GH100 440 ( 441 OBJGPU *pGpu, 442 KernelGsp *pKernelGsp 443 ) 444 { 445 KernelFalcon *pKernelFalcon = staticCast(pKernelGsp, KernelFalcon); 446 RmPhysAddr physAddr; 447 448 // Reset the GSP to prepare for RISCV bootstrap 449 kgspResetHw_HAL(pGpu, pKernelGsp); 450 451 // Stuff the GSP-FMC arguments into the mailbox regs 452 physAddr = memdescGetPhysAddr(pKernelGsp->pGspFmcArgumentsDescriptor, AT_GPU, 0); 453 kflcnRegWrite_HAL(pGpu, pKernelFalcon, NV_PFALCON_FALCON_MAILBOX0, NvU64_LO32(physAddr)); 454 kflcnRegWrite_HAL(pGpu, pKernelFalcon, NV_PFALCON_FALCON_MAILBOX1, NvU64_HI32(physAddr)); 455 456 // CC needs additional "regkeys" stuffed in a separate mailbox for the init partition 457 ConfidentialCompute *pConfCompute = GPU_GET_CONF_COMPUTE(pGpu); 458 GPU_REG_WR32(pGpu, NV_PGSP_MAILBOX(0), pConfCompute->gspProxyRegkeys); 459 460 // Bootstrap the GSP-FMC by pointing the GSP's BootROM at it 461 RM_RISCV_UCODE_DESC *pRiscvDesc = pKernelGsp->pGspRmBootUcodeDesc; 462 RmPhysAddr fmcPhysAddr = memdescGetPhysAddr(pKernelGsp->pGspRmBootUcodeMemdesc, AT_GPU, 0); 463 464 // Program FMC code DMAADDR 465 physAddr = (fmcPhysAddr + pRiscvDesc->monitorCodeOffset) >> RISCV_BR_ADDR_ALIGNMENT; 466 kflcnRiscvRegWrite_HAL(pGpu, pKernelFalcon, NV_PRISCV_RISCV_BCR_DMAADDR_FMCCODE_LO, 467 NvU64_LO32(physAddr)); 468 kflcnRiscvRegWrite_HAL(pGpu, pKernelFalcon, NV_PRISCV_RISCV_BCR_DMAADDR_FMCCODE_HI, 469 NvU64_HI32(physAddr)); 470 471 // Program FMC Data DMAADDR 472 physAddr = (fmcPhysAddr + pRiscvDesc->monitorDataOffset) >> RISCV_BR_ADDR_ALIGNMENT; 473 kflcnRiscvRegWrite_HAL(pGpu, pKernelFalcon, NV_PRISCV_RISCV_BCR_DMAADDR_FMCDATA_LO, 474 NvU64_LO32(physAddr)); 475 kflcnRiscvRegWrite_HAL(pGpu, pKernelFalcon, NV_PRISCV_RISCV_BCR_DMAADDR_FMCDATA_HI, 476 NvU64_HI32(physAddr)); 477 478 // Program manifest DMAADDR 479 physAddr = (fmcPhysAddr + pRiscvDesc->manifestOffset) >> RISCV_BR_ADDR_ALIGNMENT; 480 kflcnRiscvRegWrite_HAL(pGpu, pKernelFalcon, NV_PRISCV_RISCV_BCR_DMAADDR_PKCPARAM_LO, 481 NvU64_LO32(physAddr)); 482 kflcnRiscvRegWrite_HAL(pGpu, pKernelFalcon, NV_PRISCV_RISCV_BCR_DMAADDR_PKCPARAM_HI, 483 NvU64_HI32(physAddr)); 484 485 NvU32 target = NV_PRISCV_RISCV_BCR_DMACFG_TARGET_COHERENT_SYSMEM; 486 NvU32 dmaCfg = DRF_NUM(_PRISCV_RISCV, _BCR_DMACFG, _TARGET, target) | 487 DRF_DEF(_PRISCV_RISCV, _BCR_DMACFG, _LOCK, _LOCKED); 488 489 kflcnRiscvRegWrite_HAL(pGpu, pKernelFalcon, NV_PRISCV_RISCV_BCR_DMACFG, dmaCfg); 490 491 kflcnRiscvProgramBcr_HAL(pGpu, pKernelFalcon, NV_TRUE); 492 493 // Start it 494 kflcnRiscvRegWrite_HAL(pGpu, pKernelFalcon, NV_PRISCV_RISCV_CPUCTL, 495 DRF_DEF(_PRISCV_RISCV, _CPUCTL, _STARTCPU, _TRUE)); 496 } 497 498 /*! 499 * Boot GSP-RM. 500 * 501 * This routine handles the following: 502 * - prepares RISCV core to run GSP-RM 503 * - prepares libos initialization args 504 * - prepares GSP-RM initialization message 505 * - starts the RISCV core and passes control to boot binary image 506 * - waits for GSP-RM to complete initialization 507 * 508 * Note that this routine is based on flcnBootstrapRiscvOS_GA102(). 509 * 510 * @param[in] pGpu GPU object pointer 511 * @param[in] pKernelGsp GSP object pointer 512 * @param[in] pGspFw GSP_FIRMWARE image pointer 513 * 514 * @return NV_OK if GSP-RM RISCV boot was successful. 515 * Appropriate NV_ERR_xxx value otherwise. 516 */ 517 NV_STATUS 518 kgspBootstrapRiscvOSEarly_GH100 519 ( 520 OBJGPU *pGpu, 521 KernelGsp *pKernelGsp, 522 GSP_FIRMWARE *pGspFw 523 ) 524 { 525 KernelFalcon *pKernelFalcon = staticCast(pKernelGsp, KernelFalcon); 526 KernelFsp *pKernelFsp = GPU_GET_KERNEL_FSP(pGpu); 527 KernelMemorySystem *pKernelMemorySystem = GPU_GET_KERNEL_MEMORY_SYSTEM(pGpu); 528 NV_STATUS status = NV_OK; 529 530 // Only for GSP client builds 531 if (!IS_GSP_CLIENT(pGpu)) 532 { 533 NV_PRINTF(LEVEL_ERROR, "IS_GSP_CLIENT is not set.\n"); 534 return NV_ERR_NOT_SUPPORTED; 535 } 536 537 // Clear ECC errors before attempting to load GSP 538 status = kmemsysClearEccCounts_HAL(pGpu, pKernelMemorySystem); 539 if (status != NV_OK) 540 { 541 NV_PRINTF(LEVEL_ERROR, "Issue clearing ECC counts! Status:0x%x\n", status); 542 } 543 544 // Setup the descriptors that GSP-FMC needs to boot GSP-RM 545 NV_CHECK_OK_OR_GOTO(status, LEVEL_ERROR, 546 kgspSetupGspFmcArgs_HAL(pGpu, pKernelGsp, pGspFw), exit); 547 548 kgspSetupLibosInitArgs(pGpu, pKernelGsp); 549 550 // Fill in the GSP-RM message queue init parameters 551 kgspPopulateGspRmInitArgs(pGpu, pKernelGsp, NULL); 552 553 // 554 // Stuff the message queue with async init messages that will be run 555 // before OBJGPU is created. 556 // 557 NV_RM_RPC_GSP_SET_SYSTEM_INFO(pGpu, status); 558 if (status != NV_OK) 559 { 560 NV_ASSERT_OK_FAILED("NV_RM_RPC_GSP_SET_SYSTEM_INFO", status); 561 goto exit; 562 } 563 564 NV_RM_RPC_SET_REGISTRY(pGpu, status); 565 if (status != NV_OK) 566 { 567 NV_ASSERT_OK_FAILED("NV_RM_RPC_SET_REGISTRY", status); 568 goto exit; 569 } 570 571 if (pKernelFsp != NULL && !pKernelFsp->getProperty(pKernelFsp, PDB_PROP_KFSP_DISABLE_GSPFMC)) 572 { 573 NV_PRINTF(LEVEL_NOTICE, "Starting to boot GSP via FSP.\n"); 574 pKernelFsp->setProperty(pKernelFsp, PDB_PROP_KFSP_GSP_MODE_GSPRM, NV_TRUE); 575 NV_CHECK_OK_OR_GOTO(status, LEVEL_ERROR, 576 kfspSendBootCommands_HAL(pGpu, pKernelFsp), exit); 577 } 578 else 579 { 580 _kgspBootstrapGspFmc_GH100(pGpu, pKernelGsp); 581 } 582 583 // Wait for target mask to be released. 584 if (pKernelFsp != NULL) 585 { 586 status = kfspWaitForGspTargetMaskReleased_HAL(pGpu, pKernelFsp); 587 if (status != NV_OK) 588 { 589 NV_PRINTF(LEVEL_ERROR, "Timeout waiting for GSP target mask release. " 590 "This error may be caused by several reasons: Bootrom may have failed, " 591 "GSP init code may have failed or ACR failed to release target mask. " 592 "RM does not have access to information on which of those conditions happened.\n"); 593 594 if (pKernelFsp->getProperty(pKernelFsp, PDB_PROP_KFSP_GSP_MODE_GSPRM)) 595 { 596 kfspDumpDebugState_HAL(pGpu, pKernelFsp); 597 } 598 599 goto exit; 600 } 601 } 602 603 // Wait for lockdown to be released. 604 status = gpuTimeoutCondWait(pGpu, _kgspIsLockdownReleased, pKernelGsp, NULL); 605 if (status != NV_OK) 606 { 607 NV_PRINTF(LEVEL_ERROR, "Timeout waiting for lockdown release. It's also " 608 "possible that bootrom may have failed. RM may not have access to " 609 "the BR status to be able to say for sure what failed.\n"); 610 611 if (pKernelFsp != NULL && pKernelFsp->getProperty(pKernelFsp, PDB_PROP_KFSP_GSP_MODE_GSPRM)) 612 { 613 kfspDumpDebugState_HAL(pGpu, pKernelFsp); 614 } 615 616 NV_PRINTF(LEVEL_ERROR, "NV_PGSP_FALCON_MAILBOX0 = 0x%x\n", 617 kflcnRegRead_HAL(pGpu, pKernelFalcon, NV_PFALCON_FALCON_MAILBOX0)); 618 NV_PRINTF(LEVEL_ERROR, "NV_PGSP_FALCON_MAILBOX1 = 0x%x\n", 619 kflcnRegRead_HAL(pGpu, pKernelFalcon, NV_PFALCON_FALCON_MAILBOX1)); 620 goto exit; 621 } 622 623 // Start polling for libos logs now that lockdown is released 624 pKernelGsp->bLibosLogsPollingEnabled = NV_TRUE; 625 626 // Program FALCON_OS 627 RM_RISCV_UCODE_DESC *pRiscvDesc = pKernelGsp->pGspRmBootUcodeDesc; 628 kflcnRegWrite_HAL(pGpu, pKernelFalcon, NV_PFALCON_FALCON_OS, pRiscvDesc->appVersion); 629 630 // Ensure the CPU is started 631 if (kflcnIsRiscvActive_HAL(pGpu, pKernelFalcon)) 632 { 633 NV_PRINTF(LEVEL_INFO, "GSP ucode loaded and RISCV started.\n"); 634 } 635 else 636 { 637 NV_ASSERT_FAILED("Failed to boot GSP"); 638 status = NV_ERR_NOT_READY; 639 goto exit; 640 } 641 642 NV_PRINTF(LEVEL_INFO, "Waiting for GSP fw RM to be ready...\n"); 643 644 // Link the status queue. 645 NV_ASSERT_OK_OR_GOTO(status, GspStatusQueueInit(pGpu, &pKernelGsp->pRpc->pMessageQueueInfo), 646 exit); 647 648 NV_ASSERT_OK_OR_GOTO(status, kgspWaitForRmInitDone(pGpu, pKernelGsp), 649 exit); 650 651 NV_PRINTF(LEVEL_INFO, "GSP FW RM ready.\n"); 652 653 exit: 654 // If GSP fails to boot, check if there's any DED error. 655 if (status != NV_OK) 656 { 657 kmemsysCheckEccCounts_HAL(pGpu, pKernelMemorySystem); 658 } 659 NV_ASSERT(status == NV_OK); 660 661 return status; 662 } 663 664 void 665 kgspGetGspRmBootUcodeStorage_GH100 666 ( 667 OBJGPU *pGpu, 668 KernelGsp *pKernelGsp, 669 BINDATA_STORAGE **ppBinStorageImage, 670 BINDATA_STORAGE **ppBinStorageDesc 671 ) 672 { 673 ConfidentialCompute *pCC = GPU_GET_CONF_COMPUTE(pGpu); 674 if (pCC != NULL && pCC->getProperty(pCC, PDB_PROP_CONFCOMPUTE_CC_FEATURE_ENABLED)) 675 { 676 const BINDATA_ARCHIVE *pBinArchiveConcatenatedFMCDesc = kgspGetBinArchiveConcatenatedFMCDesc_HAL(pKernelGsp); 677 const BINDATA_ARCHIVE *pBinArchiveConcatenatedFMC = kgspGetBinArchiveConcatenatedFMC_HAL(pKernelGsp); 678 679 if (kgspIsDebugModeEnabled(pGpu, pKernelGsp)) 680 { 681 *ppBinStorageImage = (BINDATA_STORAGE *)bindataArchiveGetStorage(pBinArchiveConcatenatedFMC, "ucode_image_dbg"); 682 *ppBinStorageDesc = (BINDATA_STORAGE *)bindataArchiveGetStorage(pBinArchiveConcatenatedFMCDesc, "ucode_desc_dbg"); 683 } 684 else 685 { 686 *ppBinStorageImage = (BINDATA_STORAGE *)bindataArchiveGetStorage(pBinArchiveConcatenatedFMC, "ucode_image_prod"); 687 *ppBinStorageDesc = (BINDATA_STORAGE *)bindataArchiveGetStorage(pBinArchiveConcatenatedFMCDesc, "ucode_desc_prod"); 688 } 689 690 return; 691 } 692 kgspGetGspRmBootUcodeStorage_GA102(pGpu, pKernelGsp, ppBinStorageImage, ppBinStorageDesc); 693 } 694