1 /* 2 * SPDX-FileCopyrightText: Copyright (c) 1993-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 #define NVOC_KERNEL_GRAPHICS_OBJECT_H_PRIVATE_ACCESS_ALLOWED 25 26 #include "kernel/gpu/gr/kernel_graphics_manager.h" 27 #include "kernel/gpu/gr/kernel_graphics.h" 28 #include "kernel/core/locks.h" 29 #include "kernel/gpu/subdevice/subdevice.h" 30 #include "vgpu/rpc.h" 31 #include "kernel/mem_mgr/gpu_vaspace.h" 32 #include "kernel/gpu/mem_mgr/mem_mgr.h" 33 #include "kernel/gpu/fifo/kernel_channel_group.h" 34 #include "kernel/gpu/fifo/kernel_channel_group_api.h" 35 36 #include "class/cl0020.h" 37 38 #include "ctrl/ctrl2080/ctrl2080gr.h" // NV2080_CTRL_GR_ROUTE_INFO 39 40 /*! 41 * This function calls promote context RPC to promote GR buffers. 42 * Each ctx buffer may or may not may not have its PA updated (initialized) in 43 * physical RM, and each ctx buffer should have its VA updated (promoted) in 44 * physical RM at least once per VAS, of which there may be multiple in a TSG. 45 * When UVM is enabled, this function is responsible only for updating the PA of 46 * a given context buffer, and not the VA. 47 */ 48 NV_STATUS 49 kgrobjPromoteContext_IMPL 50 ( 51 OBJGPU *pGpu, 52 KernelGraphicsObject *pKernelGraphicsObject, 53 KernelGraphics *pKernelGraphics 54 ) 55 { 56 NvU32 promoteIds[NV2080_CTRL_GPU_PROMOTE_CONTEXT_MAX_ENTRIES]; 57 NvU32 promoteIdsSize; 58 NvBool bAttemptPromote; 59 NvU32 i; 60 NV2080_CTRL_GPU_PROMOTE_CTX_PARAMS params; 61 NvU32 entryCount; 62 RM_API *pRmApi = rmapiGetInterface(RMAPI_GPU_LOCK_INTERNAL); 63 NV_STATUS status; 64 Device *pDevice = GPU_RES_GET_DEVICE(pKernelGraphicsObject); 65 Subdevice *pSubdevice; 66 ChannelDescendant *pChannelDescendant = staticCast(pKernelGraphicsObject, ChannelDescendant); 67 68 if (IS_MODS_AMODEL(pGpu)) 69 return NV_OK; 70 71 NV_ASSERT_OK_OR_RETURN( 72 subdeviceGetByDeviceAndGpu( 73 RES_GET_CLIENT(pKernelGraphicsObject), 74 pDevice, 75 pGpu, 76 &pSubdevice)); 77 78 GPU_RES_SET_THREAD_BC_STATE(pSubdevice); 79 80 kgrobjGetPromoteIds_HAL(pGpu, pKernelGraphicsObject, 81 NV_ARRAY_ELEMENTS(promoteIds), 82 promoteIds, 83 &promoteIdsSize, 84 &bAttemptPromote); 85 86 if (promoteIdsSize == 0) 87 return NV_OK; 88 89 portMemSet(¶ms, 0, sizeof(params)); 90 91 entryCount = 0; 92 for (i = 0; i < promoteIdsSize; ++i) 93 { 94 NvBool bInitialize; 95 NvBool bPromote = NV_FALSE; 96 97 // Setup parameters to initialize the PA if necessary 98 NV_ASSERT_OK_OR_RETURN( 99 kgrctxPrepareInitializeCtxBuffer(pGpu, 100 pKernelGraphicsObject->pKernelGraphicsContext, 101 pKernelGraphics, 102 pChannelDescendant->pKernelChannel, 103 promoteIds[i], 104 ¶ms.promoteEntry[entryCount], 105 &bInitialize)); 106 107 if (bAttemptPromote) 108 { 109 // Setup parameters to promote the VA if necessary 110 NV_ASSERT_OK_OR_RETURN( 111 kgrctxPreparePromoteCtxBuffer(pGpu, 112 pKernelGraphicsObject->pKernelGraphicsContext, 113 pChannelDescendant->pKernelChannel, 114 promoteIds[i], 115 ¶ms.promoteEntry[entryCount], 116 &bPromote)); 117 } 118 119 // If initialization / promotion was necessary, then move to next index 120 if (bInitialize || bPromote) 121 entryCount++; 122 } 123 124 // Nothing to promote, so return early 125 if (entryCount == 0) 126 return NV_OK; 127 128 params.engineType = NV2080_ENGINE_TYPE_GR(kgraphicsGetInstance(pGpu, pKernelGraphics)); 129 params.hChanClient = RES_GET_CLIENT_HANDLE(pChannelDescendant); 130 params.hObject = RES_GET_PARENT_HANDLE(pChannelDescendant); 131 params.entryCount = entryCount; 132 133 status = pRmApi->Control(pRmApi, 134 RES_GET_CLIENT_HANDLE(pSubdevice), 135 RES_GET_HANDLE(pSubdevice), 136 NV2080_CTRL_CMD_GPU_PROMOTE_CTX, 137 ¶ms, 138 sizeof(params)); 139 140 if (status == NV_OK) 141 { 142 // 143 // If we successfully promoted the PA, flip a flag to ensure we don't 144 // try to promote it again. The VA_LIST should already track this for 145 // VA, but we can't rely on it for PA due to UVM. 146 // 147 for (i = 0; i < entryCount; ++i) 148 { 149 if (!params.promoteEntry[i].bInitialize) 150 continue; 151 152 kgrctxMarkCtxBufferInitialized(pGpu, 153 pKernelGraphicsObject->pKernelGraphicsContext, 154 pKernelGraphics, 155 pChannelDescendant->pKernelChannel, 156 params.promoteEntry[i].bufferId); 157 } 158 } 159 160 return status; 161 } 162 163 /*! 164 * @brief Construct the Kernel GR object for the given GPU 165 * 166 * @param[in] pGpu 167 * @param[in] pKernelGraphics 168 * @param[in] pKernelGraphicsObject 169 */ 170 static NV_STATUS 171 _kgrAlloc 172 ( 173 OBJGPU *pGpu, 174 KernelGraphics *pKernelGraphics, 175 KernelGraphicsObject *pKernelGraphicsObject 176 ) 177 { 178 ChannelDescendant *pChannelDescendant = staticCast(pKernelGraphicsObject, ChannelDescendant); 179 NvU32 numGpcs; 180 NvU32 classNum = pChannelDescendant->resourceDesc.externalClassId; 181 const KGRAPHICS_STATIC_INFO *pKernelGraphicsStaticInfo = kgraphicsGetStaticInfo(pGpu, pKernelGraphics); 182 NvU32 gfid = kchannelGetGfid(pChannelDescendant->pKernelChannel); 183 184 NV_ASSERT_OR_RETURN(pKernelGraphicsStaticInfo != NULL, NV_ERR_INVALID_STATE); 185 186 // Prevent ctx creation on sys pipes with 0 GPCs attached 187 if (!IS_MODS_AMODEL(pGpu)) 188 { 189 numGpcs = nvPopCount32(pKernelGraphicsStaticInfo->floorsweepingMasks.gpcMask); 190 NV_CHECK_OR_RETURN(LEVEL_ERROR, numGpcs > 0, NV_ERR_INSUFFICIENT_RESOURCES); 191 } 192 193 // Each object may need to create an Mmio mapping 194 NV_CHECK_OK_OR_RETURN(LEVEL_ERROR, 195 kgrobjSetComputeMmio_HAL(pGpu, pKernelGraphicsObject)); 196 197 // Ensure that ctx buffer information is initialized 198 if (!IS_MODS_AMODEL(pGpu)) 199 { 200 NV_ASSERT_OK_OR_RETURN( 201 kgraphicsInitializeDeferredStaticData(pGpu, pKernelGraphics, NV01_NULL_OBJECT, NV01_NULL_OBJECT)); 202 } 203 204 // Allocate FECS buffer in Guest for SRIOV configs. 205 if (kgrctxShouldManageCtxBuffers_HAL(pGpu, pKernelGraphicsObject->pKernelGraphicsContext, gfid) || IS_VIRTUAL_WITH_SRIOV(pGpu)) 206 { 207 NV_CHECK_OK_OR_RETURN(LEVEL_ERROR, 208 kgraphicsAllocKgraphicsBuffers_HAL(pGpu, pKernelGraphics, pKernelGraphicsObject->pKernelGraphicsContext, pChannelDescendant->pKernelChannel)); 209 } 210 211 if (kgrctxShouldManageCtxBuffers_HAL(pGpu, pKernelGraphicsObject->pKernelGraphicsContext, gfid)) 212 { 213 NV_CHECK_OK_OR_RETURN(LEVEL_ERROR, 214 kgrctxAllocCtxBuffers(pGpu, pKernelGraphicsObject->pKernelGraphicsContext, pKernelGraphics, pKernelGraphicsObject)); 215 216 NV_CHECK_OK_OR_RETURN(LEVEL_ERROR, 217 kgrctxMapCtxBuffers(pGpu, pKernelGraphicsObject->pKernelGraphicsContext, pKernelGraphics, pKernelGraphicsObject)); 218 } 219 220 kgrctxIncObjectCount_HAL(pGpu, pKernelGraphicsObject->pKernelGraphicsContext, classNum); 221 222 NV_CHECK_OK_OR_RETURN(LEVEL_ERROR, 223 kgrobjPromoteContext(pGpu, pKernelGraphicsObject, pKernelGraphics)); 224 225 return NV_OK; 226 } 227 228 /*! 229 * @brief Destruct the Kernel GR object 230 * 231 * @param[in] pKernelGraphicsObject 232 * @param[in] bDestructor NV_TRUE if called from destructor, used to share 233 * cleanup code with constructor 234 */ 235 static void _kgrobjDestruct 236 ( 237 KernelGraphicsObject *pKernelGraphicsObject, 238 NvBool bDestructor 239 ) 240 { 241 OBJGPU *pGpu = GPU_RES_GET_GPU(pKernelGraphicsObject); 242 243 SLI_LOOP_START(SLI_LOOP_FLAGS_BC_ONLY | SLI_LOOP_FLAGS_IGNORE_REENTRANCY) 244 { 245 ChannelDescendant *pChannelDescendant = staticCast(pKernelGraphicsObject, ChannelDescendant); 246 NV_STATUS status = NV_OK; 247 KernelGraphicsManager *pKernelGraphicsManager = GPU_GET_KERNEL_GRAPHICS_MANAGER(pGpu); 248 KernelGraphics *pKernelGraphics; 249 NV2080_CTRL_GR_ROUTE_INFO grRouteInfo = {0}; 250 Device *pDevice = GPU_RES_GET_DEVICE(pChannelDescendant); 251 NvHandle hParent = RES_GET_PARENT_HANDLE(pChannelDescendant); 252 NvU32 classNum = pChannelDescendant->resourceDesc.externalClassId; 253 254 // If MIG is enabled, perform GR instance routing based upon parent channel handle 255 kgrmgrCtrlSetChannelHandle(hParent, &grRouteInfo); 256 NV_ASSERT_OK_OR_CAPTURE_FIRST_ERROR(status, 257 kgrmgrCtrlRouteKGRWithDevice(pGpu, pKernelGraphicsManager, pDevice, &grRouteInfo, &pKernelGraphics)); 258 259 if (status != NV_OK) 260 SLI_LOOP_CONTINUE; 261 262 // Free Compute Mmio mapping 263 kgrobjFreeComputeMmio_HAL(pGpu, pKernelGraphicsObject); 264 265 if (bDestructor) 266 kgrctxDecObjectCount_HAL(pGpu, pKernelGraphicsObject->pKernelGraphicsContext, classNum); 267 268 if (kgrobjShouldCleanup_HAL(pGpu, pKernelGraphicsObject)) 269 { 270 kgrctxUnmapCtxBuffers(pGpu, 271 pKernelGraphicsObject->pKernelGraphicsContext, 272 pKernelGraphicsObject, 273 pKernelGraphics, 274 bDestructor); 275 } 276 } 277 SLI_LOOP_END; 278 } 279 280 // 281 // Graphics engine object creation routine. 282 // 283 NV_STATUS 284 kgrobjConstruct_IMPL 285 ( 286 KernelGraphicsObject *pKernelGraphicsObject, 287 CALL_CONTEXT *pCallContext, 288 RS_RES_ALLOC_PARAMS_INTERNAL *pParams 289 ) 290 { 291 ChannelDescendant *pChannelDescendant = staticCast(pKernelGraphicsObject, ChannelDescendant); 292 KernelChannel *pKernelChannel = pChannelDescendant->pKernelChannel; 293 NV_STATUS status = NV_OK; 294 OBJGPU *pGpu = GPU_RES_GET_GPU(pChannelDescendant); 295 Device *pDevice = GPU_RES_GET_DEVICE(pKernelGraphicsObject); 296 297 NV_ASSERT_OR_RETURN(pKernelChannel != NULL, NV_ERR_INVALID_STATE); 298 299 NV_PRINTF(LEVEL_INFO, "class: 0x%x on channel: 0x%08x\n", 300 pChannelDescendant->resourceDesc.externalClassId, kchannelGetDebugTag(pKernelChannel)); 301 302 // 303 // Legacy code believed this to be possible, but Resource Server should 304 // prevent NV01_NULL_OBJECT from being chosen as a handle. 305 // 306 NV_ASSERT_OR_RETURN(pParams->hResource != NV01_NULL_OBJECT, 307 NV_ERR_INVALID_STATE); 308 309 { 310 KernelChannel *pkChannel = pChannelDescendant->pKernelChannel; 311 312 NV_ASSERT_OR_RETURN(pkChannel != NULL, NV_ERR_INVALID_STATE); 313 314 if (kgrctxFromKernelChannel(pkChannel, &pKernelGraphicsObject->pKernelGraphicsContext) == NV_OK) 315 { 316 KernelGraphicsContext *pKernelGraphicsContext = pKernelGraphicsObject->pKernelGraphicsContext; 317 318 // 319 // Add each gr object as a dependant of the context such that all 320 // objects are guaranteed to be torn down before the context 321 // 322 refAddDependant(RES_GET_REF(pKernelGraphicsContext), 323 RES_GET_REF(pKernelGraphicsObject)); 324 325 } 326 } 327 328 SLI_LOOP_START(SLI_LOOP_FLAGS_BC_ONLY | SLI_LOOP_FLAGS_IGNORE_REENTRANCY) 329 { 330 KernelGraphicsManager *pKernelGraphicsManager = GPU_GET_KERNEL_GRAPHICS_MANAGER(pGpu); 331 KernelGraphics *pKernelGraphics; 332 NV2080_CTRL_GR_ROUTE_INFO grRouteInfo = {0}; 333 334 // If MIG is enabled, perform GR instance routing based upon parent channel handle 335 kgrmgrCtrlSetChannelHandle(pParams->hParent, &grRouteInfo); 336 NV_ASSERT_OK_OR_CAPTURE_FIRST_ERROR(status, 337 kgrmgrCtrlRouteKGRWithDevice(pGpu, pKernelGraphicsManager, pDevice, &grRouteInfo, &pKernelGraphics)); 338 if (status != NV_OK) 339 SLI_LOOP_BREAK; 340 341 // Construct the Kernel Object 342 status = _kgrAlloc(pGpu, pKernelGraphics, pKernelGraphicsObject); 343 344 if (status != NV_OK) 345 SLI_LOOP_BREAK; 346 } 347 SLI_LOOP_END; 348 349 // failed 350 if (status != NV_OK) 351 { 352 // Destroy the kernel object from the constructor 353 _kgrobjDestruct(pKernelGraphicsObject, NV_FALSE); 354 } 355 356 return status; 357 } 358 359 /*! 360 * @brief GR object Destructor 361 * 362 * @param[in] pKernelGraphicsObject 363 */ 364 void 365 kgrobjDestruct_IMPL 366 ( 367 KernelGraphicsObject *pKernelGraphicsObject 368 ) 369 { 370 // Destroy the kernel object from the destructor 371 _kgrobjDestruct(pKernelGraphicsObject, NV_TRUE); 372 } 373 374 NV_STATUS 375 kgrobjGetMemInterMapParams_IMPL 376 ( 377 KernelGraphicsObject *pKernelGraphicsObject, 378 RMRES_MEM_INTER_MAP_PARAMS *pParams 379 ) 380 { 381 MEMORY_DESCRIPTOR *pSrcMemDesc = pKernelGraphicsObject->pMmioMemDesc; 382 383 if (pParams->bSubdeviceHandleProvided) 384 { 385 NV_PRINTF(LEVEL_ERROR, "Unicast DMA mappings of non-memory objects not supported.\n"); 386 return NV_ERR_NOT_SUPPORTED; 387 } 388 389 if (pSrcMemDesc == NULL) 390 return NV_ERR_INVALID_OBJECT_HANDLE; 391 392 pParams->pSrcMemDesc = pSrcMemDesc; 393 pParams->pSrcGpu = pSrcMemDesc->pGpu; 394 395 return NV_OK; 396 } 397 398 /*! 399 * @brief Set up MMIO memDesc for Compute Object 400 */ 401 NV_STATUS 402 kgrobjSetComputeMmio_IMPL 403 ( 404 OBJGPU *pGpu, 405 KernelGraphicsObject *pKernelGraphicsObject 406 ) 407 { 408 ChannelDescendant *pChanDes = staticCast(pKernelGraphicsObject, ChannelDescendant); 409 MemoryManager *pMemoryManager = GPU_GET_MEMORY_MANAGER(pGpu); 410 NvU32 classNum = pChanDes->resourceDesc.externalClassId; 411 NvU32 objType; 412 413 kgrmgrGetGrObjectType(classNum, &objType); 414 415 // Nothing to do for non-compute 416 if (objType != GR_OBJECT_TYPE_COMPUTE) 417 return NV_OK; 418 419 // This can be called multiple times in SLI, so just skip it if present 420 if (pKernelGraphicsObject->pMmioMemDesc != NULL) 421 return NV_OK; 422 423 // Set up MMIO memDesc to allow GPU mappings of compute object 424 NV_CHECK_OK_OR_RETURN(LEVEL_ERROR, 425 memdescCreate(&pKernelGraphicsObject->pMmioMemDesc, pGpu, RM_PAGE_SIZE, 0, 426 NV_TRUE, ADDR_FBMEM, NV_MEMORY_UNCACHED, 427 MEMDESC_FLAGS_NONE)); 428 429 // 430 // The address field is completely ignored for these mappings. We use the 431 // chid as the address strictly for debug purposes. 432 // 433 memdescDescribe(pKernelGraphicsObject->pMmioMemDesc, ADDR_FBMEM /* Ignored */, 434 RM_PAGE_SIZE * pChanDes->pKernelChannel->ChID, 435 RM_PAGE_SIZE); 436 memdescSetPteKind(pKernelGraphicsObject->pMmioMemDesc, 437 memmgrGetMessageKind_HAL(pGpu, pMemoryManager)); 438 439 memmgrSetMemDescPageSize_HAL(pGpu, pMemoryManager, pKernelGraphicsObject->pMmioMemDesc, AT_GPU, 440 RM_ATTR_PAGE_SIZE_4KB); 441 442 return NV_OK; 443 } 444 445 /*! 446 * @brief Free up MMIO memDesc for Compute Object 447 */ 448 void 449 kgrobjFreeComputeMmio_IMPL 450 ( 451 OBJGPU *pGpu, 452 KernelGraphicsObject *pKernelGraphicsObject 453 ) 454 { 455 memdescDestroy(pKernelGraphicsObject->pMmioMemDesc); 456 pKernelGraphicsObject->pMmioMemDesc = NULL; 457 } 458 459 /*! 460 * @brief Should we perform grobj cleanup? 461 * If client RM is not managing the ctx buffers, kernel RM should not unmap ctx buffers 462 */ 463 NvBool 464 kgrobjShouldCleanup_KERNEL 465 ( 466 OBJGPU *pGpu, 467 KernelGraphicsObject *pKernelGraphicsObject 468 ) 469 { 470 ChannelDescendant *pChannelDescendant = staticCast(pKernelGraphicsObject, ChannelDescendant); 471 NvU32 gfid = kchannelGetGfid(pChannelDescendant->pKernelChannel); 472 473 return gpuIsClientRmAllocatedCtxBufferEnabled(pGpu) && !IS_GFID_VF(gfid); 474 } 475 476 /*! 477 * @brief Should we perform grobj cleanup? 478 * If client RM is managing the ctx buffers, physical RM should not unmap ctx buffers 479 */ 480 NvBool 481 kgrobjShouldCleanup_PHYSICAL 482 ( 483 OBJGPU *pGpu, 484 KernelGraphicsObject *pKernelGraphicsObject 485 ) 486 { 487 ChannelDescendant *pChannelDescendant = staticCast(pKernelGraphicsObject, ChannelDescendant); 488 NvU32 gfid = kchannelGetGfid(pChannelDescendant->pKernelChannel); 489 490 return !gpuIsClientRmAllocatedCtxBufferEnabled(pGpu) || (gpuIsSriovEnabled(pGpu) && IS_GFID_PF(gfid)); 491 } 492 493 /*! 494 * @brief Retrieve the IDs of ctx buffers which need to be promoted for this ctx 495 * This version only serves SRIOV-Heavy, which allocates just the FECS 496 * event buffer in guest RM and promotes its PA to the host, while the 497 * rest of the buffers are managed by the host. 498 */ 499 void 500 kgrobjGetPromoteIds_VF 501 ( 502 OBJGPU *pGpu, 503 KernelGraphicsObject *pKernelGraphicsObject, 504 NvU32 maxPromoteIds, 505 NvU32 *pPromoteIds, 506 NvU32 *pNumEntries, 507 NvBool *pbPromote 508 ) 509 { 510 void kgrobjGetPromoteIds_FWCLIENT(OBJGPU *, KernelGraphicsObject *, NvU32, NvU32 *, NvU32 *, NvBool *); 511 NvU32 promoteSriovHeavy[] = 512 { 513 // 514 // For SRIOV Heavy, guest allocates FECS event buffer and informs host 515 // of its address, other buffers are managed by host 516 // 517 NV2080_CTRL_GPU_PROMOTE_CTX_BUFFER_ID_FECS_EVENT 518 }; 519 NvBool bSriovHeavyEnabled = gpuIsWarBug200577889SriovHeavyEnabled(pGpu); 520 521 if (!bSriovHeavyEnabled) 522 { 523 // Use the same implementation as FWCLIENT 524 kgrobjGetPromoteIds_FWCLIENT(pGpu, pKernelGraphicsObject, maxPromoteIds, pPromoteIds, pNumEntries, pbPromote); 525 return; 526 } 527 528 *pNumEntries = 0; 529 // SRIOV Heavy only initializes and does not promote the FECS buffer 530 *pbPromote = NV_FALSE; 531 532 NV_ASSERT_OR_RETURN_VOID(NV_ARRAY_ELEMENTS(promoteSriovHeavy) <= maxPromoteIds); 533 *pNumEntries = NV_ARRAY_ELEMENTS(promoteSriovHeavy); 534 portMemCopy(pPromoteIds, sizeof(promoteSriovHeavy), promoteSriovHeavy, sizeof(promoteSriovHeavy)); 535 } 536 537 /*! 538 * @brief Retrieve the IDs of ctx buffers which need to be promoted for this ctx 539 * This version serves SRIOV and FWCLIENT, which allocate and map the ctx 540 * buffers themselves and promote the PA/VA to host RM. 541 */ 542 void 543 kgrobjGetPromoteIds_FWCLIENT 544 ( 545 OBJGPU *pGpu, 546 KernelGraphicsObject *pKernelGraphicsObject, 547 NvU32 maxPromoteIds, 548 NvU32 *pPromoteIds, 549 NvU32 *pNumEntries, 550 NvBool *pbPromote 551 ) 552 { 553 ChannelDescendant *pChannelDescendant = staticCast(pKernelGraphicsObject, ChannelDescendant); 554 NvBool bAcquire3d; 555 556 // Buffers which need to be promoted if we are not allocating a 3d context 557 NvU32 promoteNon3d[] = 558 { 559 NV2080_CTRL_GPU_PROMOTE_CTX_BUFFER_ID_MAIN, 560 NV2080_CTRL_GPU_PROMOTE_CTX_BUFFER_ID_PM, 561 NV2080_CTRL_GPU_PROMOTE_CTX_BUFFER_ID_PATCH, 562 NV2080_CTRL_GPU_PROMOTE_CTX_BUFFER_ID_FECS_EVENT, 563 NV2080_CTRL_GPU_PROMOTE_CTX_BUFFER_ID_PRIV_ACCESS_MAP, 564 NV2080_CTRL_GPU_PROMOTE_CTX_BUFFER_ID_UNRESTRICTED_PRIV_ACCESS_MAP 565 }; 566 // Buffers which need to be promoted if we are allocating a 3d context 567 NvU32 promote3d[] = 568 { 569 NV2080_CTRL_GPU_PROMOTE_CTX_BUFFER_ID_MAIN, 570 NV2080_CTRL_GPU_PROMOTE_CTX_BUFFER_ID_PM, 571 NV2080_CTRL_GPU_PROMOTE_CTX_BUFFER_ID_PATCH, 572 NV2080_CTRL_GPU_PROMOTE_CTX_BUFFER_ID_BUFFER_BUNDLE_CB, 573 NV2080_CTRL_GPU_PROMOTE_CTX_BUFFER_ID_PAGEPOOL, 574 NV2080_CTRL_GPU_PROMOTE_CTX_BUFFER_ID_ATTRIBUTE_CB, 575 NV2080_CTRL_GPU_PROMOTE_CTX_BUFFER_ID_RTV_CB_GLOBAL, 576 NV2080_CTRL_GPU_PROMOTE_CTX_BUFFER_ID_GFXP_POOL, 577 NV2080_CTRL_GPU_PROMOTE_CTX_BUFFER_ID_GFXP_CTRL_BLK, 578 NV2080_CTRL_GPU_PROMOTE_CTX_BUFFER_ID_FECS_EVENT, 579 NV2080_CTRL_GPU_PROMOTE_CTX_BUFFER_ID_PRIV_ACCESS_MAP, 580 NV2080_CTRL_GPU_PROMOTE_CTX_BUFFER_ID_UNRESTRICTED_PRIV_ACCESS_MAP 581 }; 582 583 *pNumEntries = 0; 584 *pbPromote = NV_TRUE; 585 586 if (!gpuIsClientRmAllocatedCtxBufferEnabled(pGpu)) 587 return; 588 589 // Do we need to promote any 3D-specific context buffers? 590 if (pChannelDescendant->pKernelChannel->pKernelChannelGroupApi->pKernelChannelGroup->bLegacyMode) 591 { 592 bAcquire3d = NV_TRUE; 593 } 594 else 595 { 596 NvU32 classNum = pChannelDescendant->resourceDesc.externalClassId; 597 NvU32 objType; 598 kgrmgrGetGrObjectType(classNum, &objType); 599 bAcquire3d = ((objType == GR_OBJECT_TYPE_2D) || (objType == GR_OBJECT_TYPE_3D)); 600 } 601 602 // Determine which set of buffers we need to try to init/promote 603 if (bAcquire3d) 604 { 605 NV_ASSERT_OR_RETURN_VOID(NV_ARRAY_ELEMENTS(promote3d) <= maxPromoteIds); 606 *pNumEntries = NV_ARRAY_ELEMENTS(promote3d); 607 portMemCopy(pPromoteIds, sizeof(promote3d), promote3d, sizeof(promote3d)); 608 } 609 else 610 { 611 NV_ASSERT_OR_RETURN_VOID(NV_ARRAY_ELEMENTS(promoteNon3d) <= maxPromoteIds); 612 *pNumEntries = NV_ARRAY_ELEMENTS(promoteNon3d); 613 portMemCopy(pPromoteIds, sizeof(promoteNon3d), promoteNon3d, sizeof(promoteNon3d)); 614 } 615 } 616 617 /*! 618 * @brief Retrieve the IDs of ctx buffers which need to be promoted for this ctx 619 * This version serves bare metal and GSP when these environments are 620 * managing the ctx buffers. There is additional physical-only 621 * initialization required for these buffers on allocation which would 622 * otherwise be handled when these buffers are promoted from client RM, 623 * but in absence of above should be called manually by physical RM to 624 * keep the flow / initialization consistent. 625 */ 626 void 627 kgrobjGetPromoteIds_PHYSICAL 628 ( 629 OBJGPU *pGpu, 630 KernelGraphicsObject *pKernelGraphicsObject, 631 NvU32 maxPromoteIds, 632 NvU32 *pPromoteIds, 633 NvU32 *pNumEntries, 634 NvBool *pbPromote 635 ) 636 { 637 ChannelDescendant *pChannelDescendant = staticCast(pKernelGraphicsObject, ChannelDescendant); 638 NvU32 gfid = kchannelGetGfid(pChannelDescendant->pKernelChannel); 639 NvBool bAcquire3d; 640 641 // Buffers which need to be promoted if we are not allocating a 3d context 642 NvU32 promoteNon3d[] = 643 { 644 NV2080_CTRL_GPU_PROMOTE_CTX_BUFFER_ID_PATCH, 645 NV2080_CTRL_GPU_PROMOTE_CTX_BUFFER_ID_PRIV_ACCESS_MAP, 646 NV2080_CTRL_GPU_PROMOTE_CTX_BUFFER_ID_UNRESTRICTED_PRIV_ACCESS_MAP 647 }; 648 // Buffers which need to be promoted if we are allocating a 3d context 649 NvU32 promote3d[] = 650 { 651 NV2080_CTRL_GPU_PROMOTE_CTX_BUFFER_ID_PATCH, 652 NV2080_CTRL_GPU_PROMOTE_CTX_BUFFER_ID_GFXP_CTRL_BLK, 653 NV2080_CTRL_GPU_PROMOTE_CTX_BUFFER_ID_PRIV_ACCESS_MAP, 654 NV2080_CTRL_GPU_PROMOTE_CTX_BUFFER_ID_UNRESTRICTED_PRIV_ACCESS_MAP 655 }; 656 657 *pNumEntries = 0; 658 *pbPromote = NV_FALSE; 659 660 // If client is managing ctx buffers, we expect client to initialize these buffers 661 if (gpuIsClientRmAllocatedCtxBufferEnabled(pGpu) && !(gpuIsSriovEnabled(pGpu) && IS_GFID_PF(gfid))) 662 return; 663 664 // Do we need to promote any 3D-specific context buffers? 665 if (pChannelDescendant->pKernelChannel->pKernelChannelGroupApi->pKernelChannelGroup->bLegacyMode) 666 { 667 bAcquire3d = NV_TRUE; 668 } 669 else 670 { 671 NvU32 classNum = pChannelDescendant->resourceDesc.externalClassId; 672 NvU32 objType; 673 kgrmgrGetGrObjectType(classNum, &objType); 674 bAcquire3d = ((objType == GR_OBJECT_TYPE_2D) || (objType == GR_OBJECT_TYPE_3D)); 675 } 676 677 // Determine which set of buffers we need to try to init/promote 678 if (bAcquire3d) 679 { 680 NV_ASSERT_OR_RETURN_VOID(NV_ARRAY_ELEMENTS(promote3d) <= maxPromoteIds); 681 *pNumEntries = NV_ARRAY_ELEMENTS(promote3d); 682 portMemCopy(pPromoteIds, sizeof(promote3d), promote3d, sizeof(promote3d)); 683 } 684 else 685 { 686 NV_ASSERT_OR_RETURN_VOID(NV_ARRAY_ELEMENTS(promoteNon3d) <= maxPromoteIds); 687 *pNumEntries = NV_ARRAY_ELEMENTS(promoteNon3d); 688 portMemCopy(pPromoteIds, sizeof(promoteNon3d), promoteNon3d, sizeof(promoteNon3d)); 689 } 690 } 691 692