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 * KernelGsp functions and helpers for executing FWSEC ucode for FRTS.
26 *
27 * Note: Other than those suffixed by a chip name, functions here
28 * do not actually need to be HAL'd; we are simply keeping them all in
29 * one file to try to keep it self-contained.
30 */
31
32 #include "gpu/gsp/kernel_gsp.h"
33
34 #include "gpu/gpu.h"
35 #include "gpu/mem_mgr/mem_mgr.h"
36
37 #include "published/turing/tu102/dev_bus.h" // for NV_PBUS_VBIOS_SCRATCH
38 #include "published/turing/tu102/dev_fb.h" // for NV_PFB_PRI_MMU_WPR2_ADDR_HI
39 #include "published/turing/tu102/dev_gc6_island.h"
40 #include "published/turing/tu102/dev_gc6_island_addendum.h"
41
42 /*!
43 * Get size of FRTS data.
44 *
45 * Currently, FRTS data size is hard-coded to be 1MB
46 * (if FRTS exists for the chip).
47 */
48 NvU32
kgspGetFrtsSize_TU102(OBJGPU * pGpu,KernelGsp * pKernelGsp)49 kgspGetFrtsSize_TU102
50 (
51 OBJGPU *pGpu,
52 KernelGsp *pKernelGsp
53 )
54 {
55 NvU32 sizeIn4k = NV_PGC6_AON_FRTS_INPUT_WPR_SIZE_SECURE_SCRATCH_GROUP_03_0_WPR_SIZE_1MB_IN_4K;
56 return sizeIn4k * 0x1000;
57 }
58
59
60 // ---------------------------------------------------------------------------
61 // Structures and defines for FWSEC commands
62 // ---------------------------------------------------------------------------
63
64 typedef struct
65 {
66 NvU8 version;
67 NvU8 headerSize;
68 NvU8 entrySize;
69 NvU8 entryCount;
70 } FALCON_APPLICATION_INTERFACE_HEADER_V1;
71
72 typedef struct
73 {
74 NvU32 id;
75 NvU32 dmemOffset;
76 } FALCON_APPLICATION_INTERFACE_ENTRY_V1;
77
78 #define FALCON_APPLICATION_INTERFACE_ENTRY_ID_DMEMMAPPER (0x4)
79
80 typedef struct
81 {
82 NvU32 signature;
83 NvU16 version;
84 NvU16 size;
85 NvU32 cmd_in_buffer_offset;
86 NvU32 cmd_in_buffer_size;
87 NvU32 cmd_out_buffer_offset;
88 NvU32 cmd_out_buffer_size;
89 NvU32 nvf_img_data_buffer_offset;
90 NvU32 nvf_img_data_buffer_size;
91 NvU32 printfBufferHdr;
92 NvU32 ucode_build_time_stamp;
93 NvU32 ucode_signature;
94 NvU32 init_cmd;
95 NvU32 ucode_feature;
96 NvU32 ucode_cmd_mask0;
97 NvU32 ucode_cmd_mask1;
98 NvU32 multiTgtTbl;
99 } FALCON_APPLICATION_INTERFACE_DMEM_MAPPER_V3;
100
101 #define FALCON_APPLICATION_INTERFACE_DMEM_MAPPER_V3_CMD_FRTS (0x15)
102 #define FALCON_APPLICATION_INTERFACE_DMEM_MAPPER_V3_CMD_SB (0x19)
103
104 typedef struct
105 {
106 NvU32 version;
107 NvU32 size;
108 NvU64 gfwImageOffset;
109 NvU32 gfwImageSize;
110 NvU32 flags;
111 } FWSECLIC_READ_VBIOS_DESC;
112
113 #define FWSECLIC_READ_VBIOS_STRUCT_FLAGS (2)
114
115 typedef struct
116 {
117 NvU32 version;
118 NvU32 size;
119 NvU32 frtsRegionOffset4K;
120 NvU32 frtsRegionSize;
121 NvU32 frtsRegionMediaType;
122 } FWSECLIC_FRTS_REGION_DESC;
123
124 #define FWSECLIC_FRTS_REGION_MEDIA_FB (2)
125 #define FWSECLIC_FRTS_REGION_SIZE_1MB_IN_4K (0x100)
126
127 typedef struct
128 {
129 FWSECLIC_READ_VBIOS_DESC readVbiosDesc;
130 FWSECLIC_FRTS_REGION_DESC frtsRegionDesc;
131 } FWSECLIC_FRTS_CMD;
132
133 #define NV_VBIOS_FWSECLIC_SCRATCH_INDEX_0E 0x0E
134 #define NV_VBIOS_FWSECLIC_FRTS_ERR_CODE 31:16
135 #define NV_VBIOS_FWSECLIC_FRTS_ERR_CODE_NONE 0x00000000
136
137 #define NV_VBIOS_FWSECLIC_SCRATCH_INDEX_15 0x15
138 #define NV_VBIOS_FWSECLIC_SB_ERR_CODE 15:0
139 #define NV_VBIOS_FWSECLIC_SB_ERR_CODE_NONE 0x00000000
140
141
142 // ---------------------------------------------------------------------------
143 // Functions for preparing and executing FWSEC commands
144 // ---------------------------------------------------------------------------
145
146 /*!
147 * Patch DMEM of FWSEC for a given command
148 *
149 * @param[inout] pMappedData Pointer to mapped DMEM of FWSEC
150 * @param[in] mappedDataSize Number of bytes valid under pMappedData
151 * @param[in] cmd FWSEC command to invoke
152 * @param[in] pCmdBuffer Buffer containing command arguments to patch in
153 * @param[in] cmdBufferSize Size of buffer pointed by pCmdBuffer
154 * @param[in] interfaceOffset Interface offset given by VBIOS for FWSEC
155 */
156 static NV_STATUS
s_vbiosPatchInterfaceData(NvU8 * pMappedData,const NvU32 mappedDataSize,const NvU32 cmd,const void * pCmdBuffer,const NvU32 cmdBufferSize,const NvU32 interfaceOffset)157 s_vbiosPatchInterfaceData
158 (
159 NvU8 *pMappedData, // inout
160 const NvU32 mappedDataSize,
161 const NvU32 cmd,
162 const void *pCmdBuffer,
163 const NvU32 cmdBufferSize,
164 const NvU32 interfaceOffset
165 )
166 {
167 FALCON_APPLICATION_INTERFACE_HEADER_V1 *pIntFaceHdr = NULL;
168 FALCON_APPLICATION_INTERFACE_ENTRY_V1 *pIntFaceEntry = NULL;
169 FALCON_APPLICATION_INTERFACE_DMEM_MAPPER_V3 *pDmemMapper = NULL;
170
171 NvBool bSafe;
172 NvU32 index;
173
174 NvU32 curOffset;
175 NvU32 nextOffset;
176
177 if (interfaceOffset >= mappedDataSize)
178 {
179 return NV_ERR_INVALID_OFFSET;
180 }
181
182 bSafe = portSafeAddU32(interfaceOffset, sizeof(*pIntFaceHdr), &nextOffset);
183 if (!bSafe || nextOffset > mappedDataSize)
184 {
185 return NV_ERR_INVALID_OFFSET;
186 }
187
188 pIntFaceHdr = (FALCON_APPLICATION_INTERFACE_HEADER_V1 *) (pMappedData + interfaceOffset);
189 if (pIntFaceHdr->entryCount < 2)
190 {
191 NV_PRINTF(LEVEL_ERROR, "too few interface entires found for FWSEC cmd 0x%x\n", cmd);
192 return NV_ERR_INVALID_DATA;
193 }
194
195 curOffset = nextOffset;
196 for (index = 0; index < pIntFaceHdr->entryCount; index++)
197 {
198 if (curOffset >= mappedDataSize)
199 {
200 return NV_ERR_INVALID_OFFSET;
201 }
202
203 bSafe = portSafeAddU32(curOffset, sizeof(*pIntFaceEntry), &nextOffset);
204 if (!bSafe || nextOffset > mappedDataSize)
205 {
206 return NV_ERR_INVALID_OFFSET;
207 }
208
209 pIntFaceEntry = (FALCON_APPLICATION_INTERFACE_ENTRY_V1 *) (pMappedData + curOffset);
210 curOffset = nextOffset;
211
212 if (pIntFaceEntry->id == FALCON_APPLICATION_INTERFACE_ENTRY_ID_DMEMMAPPER)
213 {
214 NvU32 dmemMapperMaxOffset;
215
216 if (pIntFaceEntry->dmemOffset >= mappedDataSize)
217 {
218 return NV_ERR_INVALID_OFFSET;
219 }
220
221 bSafe = portSafeAddU32(pIntFaceEntry->dmemOffset, sizeof(*pDmemMapper),
222 &dmemMapperMaxOffset);
223 if (!bSafe || dmemMapperMaxOffset > mappedDataSize)
224 {
225 return NV_ERR_INVALID_OFFSET;
226 }
227
228 pDmemMapper = (FALCON_APPLICATION_INTERFACE_DMEM_MAPPER_V3 *)
229 (pMappedData + pIntFaceEntry->dmemOffset);
230 }
231 }
232
233 if (!pDmemMapper)
234 {
235 NV_PRINTF(LEVEL_ERROR, "failed to find required interface entry for FWSEC cmd 0x%x\n", cmd);
236 return NV_ERR_INVALID_DATA;
237 }
238
239 pDmemMapper->init_cmd = cmd;
240
241 if (pDmemMapper->cmd_in_buffer_size < cmdBufferSize)
242 {
243 NV_PRINTF(LEVEL_ERROR, "insufficient cmd buffer for FWSEC interface cmd 0x%x\n", cmd);
244 }
245
246 if (pDmemMapper->cmd_in_buffer_offset >= mappedDataSize)
247 {
248 return NV_ERR_INVALID_OFFSET;
249 }
250
251 bSafe = portSafeAddU32(pIntFaceEntry->dmemOffset, cmdBufferSize, &nextOffset);
252 if (!bSafe || nextOffset > mappedDataSize)
253 {
254 return NV_ERR_INVALID_OFFSET;
255 }
256
257 portMemCopy(pMappedData + pDmemMapper->cmd_in_buffer_offset, cmdBufferSize,
258 pCmdBuffer, cmdBufferSize);
259
260 return NV_OK;
261 }
262
263 /*!
264 * Prepare to execute a given FWSEC cmd.
265 *
266 * @param[in] pGpu OBJGPU pointer
267 * @param[in] pKernelGsp KernelGsp pointer
268 * @param[in] pFwsecUcode KernelGspFlcnUcode structure of FWSEC ucode
269 * @param[in] cmd FWSEC cmd (FRTS or SB)
270 * @param[in] frtsOffset (if cmd is FRTS) desired FB offset of FRTS data
271 * @param[out] pPreparedCmd Prepared command state to pass to kgspExecuteFwsec_TU102
272 */
273 static NV_STATUS
s_prepareForFwsec_TU102(OBJGPU * pGpu,KernelGsp * pKernelGsp,KernelGspFlcnUcode * pFwsecUcode,const NvU32 cmd,const NvU64 frtsOffset,KernelGspPreparedFwsecCmd * pPreparedCmd)274 s_prepareForFwsec_TU102
275 (
276 OBJGPU *pGpu,
277 KernelGsp *pKernelGsp,
278 KernelGspFlcnUcode *pFwsecUcode,
279 const NvU32 cmd,
280 const NvU64 frtsOffset,
281 KernelGspPreparedFwsecCmd *pPreparedCmd
282 )
283 {
284 NV_STATUS status;
285
286 FWSECLIC_READ_VBIOS_DESC readVbiosDesc;
287 FWSECLIC_FRTS_CMD frtsCmd;
288
289 void *pCmdBuffer;
290 NvU32 cmdBufferSize;
291
292 NV_ASSERT_OR_RETURN(!IS_VIRTUAL(pGpu), NV_ERR_NOT_SUPPORTED);
293 NV_ASSERT_OR_RETURN(IS_GSP_CLIENT(pGpu), NV_ERR_NOT_SUPPORTED);
294
295 NV_ASSERT_OR_RETURN(pFwsecUcode != NULL, NV_ERR_INVALID_ARGUMENT);
296 NV_ASSERT_OR_RETURN(pPreparedCmd != NULL, NV_ERR_INVALID_ARGUMENT);
297 NV_ASSERT_OR_RETURN((cmd != FALCON_APPLICATION_INTERFACE_DMEM_MAPPER_V3_CMD_FRTS) ||
298 (frtsOffset > 0), NV_ERR_INVALID_ARGUMENT);
299
300 if ((cmd != FALCON_APPLICATION_INTERFACE_DMEM_MAPPER_V3_CMD_FRTS) &&
301 (cmd != FALCON_APPLICATION_INTERFACE_DMEM_MAPPER_V3_CMD_SB))
302 {
303 NV_ASSERT(0);
304 return NV_ERR_INVALID_ARGUMENT;
305 }
306
307 pPreparedCmd->pFwsecUcode = pFwsecUcode;
308 pPreparedCmd->cmd = cmd;
309 pPreparedCmd->frtsOffset = frtsOffset;
310
311 readVbiosDesc.version = 1;
312 readVbiosDesc.size = sizeof(readVbiosDesc);
313 readVbiosDesc.gfwImageOffset = 0;
314 readVbiosDesc.gfwImageSize = 0;
315 readVbiosDesc.flags = FWSECLIC_READ_VBIOS_STRUCT_FLAGS;
316
317 if (cmd == FALCON_APPLICATION_INTERFACE_DMEM_MAPPER_V3_CMD_FRTS)
318 {
319 // FRTS takes an FRTS_CMD, here we build that up
320 NvU32 blockSizeIn4K = NV_PGC6_AON_FRTS_INPUT_WPR_SIZE_SECURE_SCRATCH_GROUP_03_0_WPR_SIZE_1MB_IN_4K;
321
322 frtsCmd.frtsRegionDesc.version = 1;
323 frtsCmd.frtsRegionDesc.size = sizeof(frtsCmd.frtsRegionDesc);
324 frtsCmd.frtsRegionDesc.frtsRegionOffset4K = (NvU32) (frtsOffset >> 12);
325 frtsCmd.frtsRegionDesc.frtsRegionSize = blockSizeIn4K;
326 frtsCmd.frtsRegionDesc.frtsRegionMediaType = FWSECLIC_FRTS_REGION_MEDIA_FB;
327
328 frtsCmd.readVbiosDesc = readVbiosDesc;
329
330 pCmdBuffer = &frtsCmd;
331 cmdBufferSize = sizeof(frtsCmd);
332
333 }
334 else // i.e. FALCON_APPLICATION_INTERFACE_DMEM_MAPPER_V3_CMD_SB
335 {
336 // SB takes READ_VBIOS_DESC directly
337 pCmdBuffer = &readVbiosDesc;
338 cmdBufferSize = sizeof(readVbiosDesc);
339 }
340
341 if (pFwsecUcode->bootType == KGSP_FLCN_UCODE_BOOT_FROM_HS)
342 {
343 KernelGspFlcnUcodeBootFromHs *pUcode = &pFwsecUcode->ucodeBootFromHs;
344 NvU8 *pMappedImage;
345 NvU8 *pMappedData;
346
347 NvBool bSafe;
348
349 NvU32 ucodeVersionVal;
350 NvU32 hsSigVersions;
351 NvU32 sigOffset;
352 NvU32 sigMaxOffset;
353
354 NV_ASSERT_OR_RETURN(pUcode->pUcodeMemDesc != NULL, NV_ERR_INVALID_ARGUMENT);
355 NV_ASSERT_OR_RETURN(pUcode->pSignatures != NULL, NV_ERR_INVALID_ARGUMENT);
356
357 ucodeVersionVal = kgspReadUcodeFuseVersion_HAL(pGpu, pKernelGsp, pUcode->ucodeId);
358
359 ucodeVersionVal = 1 << ucodeVersionVal;
360 hsSigVersions = pUcode->vbiosSigVersions;
361
362 if ((ucodeVersionVal & hsSigVersions) == 0)
363 {
364 return NV_ERR_NOT_SUPPORTED;;
365 }
366
367 sigOffset = 0;
368 while ((ucodeVersionVal & hsSigVersions & 1) == 0)
369 {
370 sigOffset += (hsSigVersions & 1) * pUcode->sigSize;
371 hsSigVersions >>= 1;
372 ucodeVersionVal >>= 1;
373 }
374
375 if (sigOffset >= pUcode->signaturesTotalSize)
376 {
377 return NV_ERR_INVALID_OFFSET;
378 }
379
380 bSafe = portSafeAddU32(sigOffset, pUcode->sigSize, &sigMaxOffset);
381 if (!bSafe || sigMaxOffset > pUcode->signaturesTotalSize)
382 {
383 return NV_ERR_INVALID_OFFSET;
384 }
385
386 pMappedImage = memdescMapInternal(pGpu, pUcode->pUcodeMemDesc, TRANSFER_FLAGS_NONE);
387 if (pMappedImage == NULL)
388 {
389 return NV_ERR_INSUFFICIENT_RESOURCES;
390 }
391 pMappedData = pMappedImage + pUcode->dataOffset;
392
393 status = s_vbiosPatchInterfaceData(pMappedData, pUcode->dmemSize, cmd,
394 pCmdBuffer, cmdBufferSize, pUcode->interfaceOffset);
395
396 portMemCopy(pMappedData + pUcode->hsSigDmemAddr, pUcode->sigSize,
397 ((NvU8 *) pUcode->pSignatures) + sigOffset, pUcode->sigSize);
398
399 memdescUnmapInternal(pGpu, pUcode->pUcodeMemDesc,
400 TRANSFER_FLAGS_DESTROY_MAPPING);
401 pMappedImage = NULL;
402 pMappedData = NULL;
403
404 if (status != NV_OK)
405 {
406 NV_PRINTF(LEVEL_ERROR, "failed to prepare interface data for FWSEC cmd 0x%x: 0x%x\n",
407 cmd, status);
408 goto out;
409 }
410 }
411 else if (pFwsecUcode->bootType == KGSP_FLCN_UCODE_BOOT_WITH_LOADER)
412 {
413 KernelGspFlcnUcodeBootWithLoader *pUcode = &pFwsecUcode->ucodeBootWithLoader;
414 NvU8 *pMappedData;
415
416 NV_ASSERT_OR_RETURN(pUcode->pCodeMemDesc != NULL, NV_ERR_INVALID_ARGUMENT);
417 NV_ASSERT_OR_RETURN(pUcode->pDataMemDesc != NULL, NV_ERR_INVALID_ARGUMENT);
418
419 pMappedData = memdescMapInternal(pGpu, pUcode->pDataMemDesc, TRANSFER_FLAGS_NONE);
420 if (pMappedData == NULL)
421 {
422 return NV_ERR_INSUFFICIENT_RESOURCES;
423 }
424
425 status = s_vbiosPatchInterfaceData(pMappedData, pUcode->dmemSize, cmd,
426 pCmdBuffer, cmdBufferSize, pUcode->interfaceOffset);
427
428 memdescUnmapInternal(pGpu, pUcode->pDataMemDesc,
429 TRANSFER_FLAGS_DESTROY_MAPPING);
430 pMappedData = NULL;
431
432 if (status != NV_OK)
433 {
434 NV_PRINTF(LEVEL_ERROR, "failed to prepare interface data for FWSEC cmd 0x%x: 0x%x\n",
435 cmd, status);
436 goto out;
437 }
438 }
439 else
440 {
441 return NV_ERR_NOT_SUPPORTED;
442 }
443
444 out:
445 if (status != NV_OK)
446 {
447 NV_PRINTF(LEVEL_ERROR, "(note: VBIOS version %s)\n", pKernelGsp->vbiosVersionStr);
448 }
449
450 return status;
451 }
452
453 /*!
454 * Execute a given FWSEC cmd and wait for completion.
455 * KernelGspPreparedFwsecCmd should be set by s_prepareForFwsec_TU102 and
456 * not filled in manually
457 *
458 * @param[in] pGpu OBJGPU pointer
459 * @param[in] pKernelGsp KernelGsp pointer
460 * @param[in] pPreparedCmd Prepared command state from s_prepareForFwsec_TU102
461 */
462 NV_STATUS
kgspExecuteFwsec_TU102(OBJGPU * pGpu,KernelGsp * pKernelGsp,KernelGspPreparedFwsecCmd * pPreparedCmd)463 kgspExecuteFwsec_TU102
464 (
465 OBJGPU *pGpu,
466 KernelGsp *pKernelGsp,
467 KernelGspPreparedFwsecCmd *pPreparedCmd
468 )
469 {
470 NV_STATUS status;
471
472 NV_ASSERT_OR_RETURN(!IS_VIRTUAL(pGpu), NV_ERR_NOT_SUPPORTED);
473 NV_ASSERT_OR_RETURN(IS_GSP_CLIENT(pGpu), NV_ERR_NOT_SUPPORTED);
474
475 NV_ASSERT_OR_RETURN(pPreparedCmd != NULL, NV_ERR_INVALID_ARGUMENT);
476
477 status = kgspExecuteHsFalcon_HAL(pGpu, pKernelGsp, pPreparedCmd->pFwsecUcode,
478 staticCast(pKernelGsp, KernelFalcon), NULL, NULL);
479
480 if (status != NV_OK)
481 {
482 NV_PRINTF(LEVEL_ERROR, "failed to execute FWSEC cmd 0x%x: status 0x%x\n", pPreparedCmd->cmd, status);
483 goto out;
484 }
485
486 if (pPreparedCmd->cmd == FALCON_APPLICATION_INTERFACE_DMEM_MAPPER_V3_CMD_FRTS)
487 {
488 NvU32 data;
489 NvU32 frtsErrCode;
490 NvU32 wpr2HiVal;
491 NvU32 wpr2LoVal;
492 NvU32 expectedLoVal;
493
494 data = GPU_REG_RD32(pGpu, NV_PBUS_VBIOS_SCRATCH(NV_VBIOS_FWSECLIC_SCRATCH_INDEX_0E));
495 frtsErrCode = DRF_VAL(_VBIOS, _FWSECLIC, _FRTS_ERR_CODE, data);
496 if (frtsErrCode != NV_VBIOS_FWSECLIC_FRTS_ERR_CODE_NONE)
497 {
498 NV_PRINTF(LEVEL_ERROR, "failed to execute FWSEC for FRTS: FRTS error code 0x%x\n", frtsErrCode);
499 status = NV_ERR_GENERIC;
500 goto out;
501 }
502
503 data = GPU_REG_RD32(pGpu, NV_PFB_PRI_MMU_WPR2_ADDR_HI);
504 wpr2HiVal = DRF_VAL(_PFB, _PRI_MMU_WPR2_ADDR_HI, _VAL, data);
505 if (wpr2HiVal == 0)
506 {
507 NV_PRINTF(LEVEL_ERROR, "failed to execute FWSEC for FRTS: no initialized WPR2 found\n");
508 status = NV_ERR_GENERIC;
509 goto out;
510 }
511
512 data = GPU_REG_RD32(pGpu, NV_PFB_PRI_MMU_WPR2_ADDR_LO);
513 wpr2LoVal = DRF_VAL(_PFB, _PRI_MMU_WPR2_ADDR_LO, _VAL, data);
514 expectedLoVal = (NvU32) (pPreparedCmd->frtsOffset >> NV_PFB_PRI_MMU_WPR2_ADDR_LO_ALIGNMENT);
515 if (wpr2LoVal != expectedLoVal)
516 {
517 NV_PRINTF(LEVEL_ERROR,
518 "failed to execute FWSEC for FRTS: WPR2 initialized at an unexpected location: 0x%08x (expected 0x%08x)\n",
519 wpr2LoVal, expectedLoVal);
520 status = NV_ERR_GENERIC;
521 goto out;
522 }
523 }
524 else // i.e. FALCON_APPLICATION_INTERFACE_DMEM_MAPPER_V3_CMD_SB
525 {
526 NvU32 data;
527 NvU32 sbErrCode;
528
529 if (!GPU_FLD_TEST_DRF_DEF(pGpu, _PGC6, _AON_SECURE_SCRATCH_GROUP_05_PRIV_LEVEL_MASK,
530 _READ_PROTECTION_LEVEL0, _ENABLE))
531 {
532 NV_PRINTF(LEVEL_ERROR, "failed to execute FWSEC for SB: GFW PLM not lowered\n");
533 status = NV_ERR_GENERIC;
534 goto out;
535 }
536
537 if (!GPU_FLD_TEST_DRF_DEF(pGpu, _PGC6, _AON_SECURE_SCRATCH_GROUP_05_0_GFW_BOOT,
538 _PROGRESS, _COMPLETED))
539 {
540 NV_PRINTF(LEVEL_ERROR, "failed to execute FWSEC for SB: GFW progress not completed\n");
541 status = NV_ERR_GENERIC;
542 goto out;
543 }
544
545 data = GPU_REG_RD32(pGpu, NV_PBUS_VBIOS_SCRATCH(NV_VBIOS_FWSECLIC_SCRATCH_INDEX_15));
546 sbErrCode = DRF_VAL(_VBIOS, _FWSECLIC, _SB_ERR_CODE, data);
547 if (sbErrCode != NV_VBIOS_FWSECLIC_SB_ERR_CODE_NONE)
548 {
549 NV_PRINTF(LEVEL_ERROR, "failed to execute FWSEC for SB: SB error code 0x%x\n", sbErrCode);
550 status = NV_ERR_GENERIC;
551 goto out;
552 }
553 }
554
555 out:
556 if (status != NV_OK)
557 {
558 NV_PRINTF(LEVEL_ERROR, "(note: VBIOS version %s)\n", pKernelGsp->vbiosVersionStr);
559 }
560
561 return status;
562 }
563
564 /*!
565 * Prepare to execute FWSEC FRTS ucode to setup FRTS
566 *
567 * @param[in] pGpu OBJGPU pointer
568 * @param[in] pKernelGsp KernelGsp pointer
569 * @param[in] pFwsecUcode KernelGspFlcnUcode structure of FWSEC ucode
570 * @param[in] frtsOffset Desired offset in FB of FRTS data and WPR2
571 * @param[out] pPreparedCmd Prepared command state to pass to kgspExecuteFwsec_TU102
572 */
573 NV_STATUS
kgspPrepareForFwsecFrts_TU102(OBJGPU * pGpu,KernelGsp * pKernelGsp,KernelGspFlcnUcode * pFwsecUcode,const NvU64 frtsOffset,KernelGspPreparedFwsecCmd * pPreparedCmd)574 kgspPrepareForFwsecFrts_TU102
575 (
576 OBJGPU *pGpu,
577 KernelGsp *pKernelGsp,
578 KernelGspFlcnUcode *pFwsecUcode,
579 const NvU64 frtsOffset,
580 KernelGspPreparedFwsecCmd *pPreparedCmd
581 )
582 {
583 return s_prepareForFwsec_TU102(pGpu, pKernelGsp, pFwsecUcode,
584 FALCON_APPLICATION_INTERFACE_DMEM_MAPPER_V3_CMD_FRTS,
585 frtsOffset, pPreparedCmd);
586 }
587
588 /*!
589 * Prepare to execute FWSEC SB ucode to setup FRTS
590 *
591 * @param[in] pGpu OBJGPU pointer
592 * @param[in] pKernelGsp KernelGsp pointer
593 * @param[in] pFwsecUcode KernelGspFlcnUcode structure of FWSEC ucode
594 * @param[out] pPreparedCmd Prepared command state to pass to kgspExecuteFwsec_TU102
595 */
596 NV_STATUS
kgspPrepareForFwsecSb_TU102(OBJGPU * pGpu,KernelGsp * pKernelGsp,KernelGspFlcnUcode * pFwsecUcode,KernelGspPreparedFwsecCmd * pPreparedCmd)597 kgspPrepareForFwsecSb_TU102
598 (
599 OBJGPU *pGpu,
600 KernelGsp *pKernelGsp,
601 KernelGspFlcnUcode *pFwsecUcode,
602 KernelGspPreparedFwsecCmd *pPreparedCmd
603 )
604 {
605 return s_prepareForFwsec_TU102(pGpu, pKernelGsp, pFwsecUcode,
606 FALCON_APPLICATION_INTERFACE_DMEM_MAPPER_V3_CMD_SB,
607 0, pPreparedCmd);
608 }