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