1 /* 2 * SPDX-FileCopyrightText: Copyright (c) 1993-2022 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 #include "rmapi/rmapi.h" 25 #include "rmapi/client.h" 26 #include "entry_points.h" 27 #include "core/locks.h" 28 #include "core/thread_state.h" 29 #include "vgpu/rpc.h" 30 #include "resource_desc.h" 31 #include "gpu/disp/disp_objs.h" 32 #include "gpu/disp/disp_channel.h" 33 #include "nvsecurityinfo.h" 34 35 #include "kernel/gpu/mig_mgr/kernel_mig_manager.h" 36 37 #include "gpu/device/device.h" 38 39 #include "class/cl0005.h" // NV01_EVENT 40 #include "class/clc574.h" // UVM_CHANNEL_RETAINER 41 42 #include "class/cl83de.h" // GT200_DEBUGGER 43 #include "gpu/gr/kernel_sm_debugger_session.h" 44 #include "kernel/gpu/rc/kernel_rc.h" 45 #include "tmr.h" 46 47 // 48 // RM Alloc & Free internal flags -- code should be migrated to use rsresdesc 49 // and rmapi types directly where possible. 50 // 51 #define RM_ALLOC_STATES_NONE 0 52 #define RM_ALLOC_STATES_INTERNAL_CLIENT_HANDLE ALLOC_STATE_INTERNAL_CLIENT_HANDLE // NVBIT(5) 53 #define RM_ALLOC_STATES_SKIP_RPC NVBIT(6) 54 #define RM_ALLOC_STATES_INTERNAL_ALLOC NVBIT(7) 55 56 #define RM_FREE_STATES_NONE 0 57 58 static void 59 rmapiResourceDescToLegacyFlags 60 ( 61 const RS_RESOURCE_DESC *pResDesc, 62 NvU32 *pAllocFlags, 63 NvU32 *pFreeFlags 64 ) 65 { 66 if (pAllocFlags) 67 { 68 *pAllocFlags = (pResDesc->flags & RS_FLAGS_ACQUIRE_GPUS_LOCK_ON_ALLOC) ? RM_LOCK_FLAGS_NONE : RM_LOCK_FLAGS_NO_GPUS_LOCK; 69 *pAllocFlags |= (pResDesc->flags & RS_FLAGS_ACQUIRE_GPU_GROUP_LOCK_ON_ALLOC) ? RM_LOCK_FLAGS_GPU_GROUP_LOCK : 0; 70 } 71 72 if (pFreeFlags) 73 { 74 *pFreeFlags = (pResDesc->flags & RS_FLAGS_ACQUIRE_GPUS_LOCK_ON_FREE) ? RM_LOCK_FLAGS_NONE : RM_LOCK_FLAGS_NO_GPUS_LOCK; 75 *pFreeFlags |= (pResDesc->flags & RS_FLAGS_ACQUIRE_GPU_GROUP_LOCK_ON_FREE) ? RM_LOCK_FLAGS_GPU_GROUP_LOCK : 0; 76 } 77 } 78 79 NvU32 80 serverAllocClientHandleBase 81 ( 82 RsServer *pServer, 83 NvBool bInternalHandle, 84 API_SECURITY_INFO *pSecInfo 85 ) 86 { 87 NvU32 handleBase; 88 NvU32 gfid = (NvU32)((NvU64)pSecInfo->pProcessToken); 89 90 if (bInternalHandle) 91 { 92 handleBase = pServer->internalHandleBase; 93 } 94 else 95 { 96 handleBase = pServer->clientHandleBase; 97 98 if (RMCFG_FEATURE_PLATFORM_GSP && IS_GFID_VF(gfid)) 99 handleBase = RS_CLIENT_GET_VF_HANDLE_BASE(gfid); 100 } 101 102 return handleBase; 103 } 104 105 NV_STATUS 106 serverAllocApiCopyIn 107 ( 108 RsServer *pServer, 109 RS_RES_ALLOC_PARAMS_INTERNAL *pRmAllocParams, 110 API_STATE **ppParamCopy 111 ) 112 { 113 NV_STATUS status; 114 API_SECURITY_INFO *pSecInfo = pRmAllocParams->pSecInfo; 115 NvBool bCopyInParams = pSecInfo->paramLocation == PARAM_LOCATION_USER; 116 RMAPI_PARAM_COPY *pParamCopy = NULL; 117 NvU32 allocParamsSize = 0; 118 void *pUserParams = pRmAllocParams->pAllocParams; 119 120 pParamCopy = (RMAPI_PARAM_COPY*)PORT_ALLOC(g_resServ.pAllocator, sizeof(*pParamCopy)); 121 if (pParamCopy == NULL) 122 { 123 status = NV_ERR_INSUFFICIENT_RESOURCES; 124 goto done; 125 } 126 portMemSet(pParamCopy, 0, sizeof(*pParamCopy)); 127 pRmAllocParams->pAllocParams = NULL; 128 129 // Setup for access to param 130 // Param size is initialized to zero, and then set via rmapiParamsCopyInit 131 RMAPI_PARAM_COPY_INIT(*pParamCopy, pRmAllocParams->pAllocParams, NV_PTR_TO_NvP64(pUserParams), allocParamsSize, 1); 132 133 // Look up param size based on hClass 134 status = rmapiParamsCopyInit(pParamCopy, pRmAllocParams->externalClassId); 135 if (NV_OK != status) 136 goto done; 137 138 // Using the per-class info set above, pull in the parameters for this allocation 139 if (pParamCopy->paramsSize > 0) 140 { 141 // gain access to client's parameters via 'pKernelCtrl' 142 status = rmapiParamsAcquire(pParamCopy, bCopyInParams); 143 if (status != NV_OK) 144 goto done; 145 } 146 147 // Prevent requesting rights before rights are enabled, just in case old code doesn't zero it properly. 148 if (!pServer->bRsAccessEnabled) 149 pRmAllocParams->pRightsRequested = NULL; 150 151 if (pRmAllocParams->pRightsRequested != NULL) 152 { 153 // copyFromUser requires a non-stack buffer, allocate one to copy into 154 RS_ACCESS_MASK *pMaskBuffer = (RS_ACCESS_MASK*)PORT_ALLOC(g_resServ.pAllocator, sizeof(RS_ACCESS_MASK)); 155 if (pMaskBuffer == NULL) 156 { 157 status = NV_ERR_INSUFFICIENT_RESOURCES; 158 goto done; 159 } 160 161 // Mask is a fixed size, just copy it directly into allocParams 162 status = rmapiParamsCopyIn("RightsRequested", 163 pMaskBuffer, 164 NV_PTR_TO_NvP64(pRmAllocParams->pRightsRequested), 165 sizeof(RS_ACCESS_MASK), 166 bCopyInParams); 167 168 portMemCopy(&pRmAllocParams->rightsRequestedCopy, sizeof(RS_ACCESS_MASK), 169 pMaskBuffer, sizeof(RS_ACCESS_MASK)); 170 171 PORT_FREE(g_resServ.pAllocator, pMaskBuffer); 172 173 if (status != NV_OK) 174 goto done; 175 176 pRmAllocParams->pRightsRequested = &pRmAllocParams->rightsRequestedCopy; 177 } 178 done: 179 if (status != NV_OK) 180 { 181 if (pParamCopy != NULL) 182 PORT_FREE(g_resServ.pAllocator, pParamCopy); 183 pParamCopy = NULL; 184 } 185 186 if (ppParamCopy != NULL) 187 *ppParamCopy = pParamCopy; 188 189 return status; 190 } 191 192 NV_STATUS 193 serverAllocApiCopyOut 194 ( 195 RsServer *pServer, 196 NV_STATUS status, 197 API_STATE *pParamCopy 198 ) 199 { 200 NV_STATUS cpStatus = NV_OK; 201 if (pParamCopy->paramsSize > 0) 202 { 203 // don't copyout if an error 204 if (status != NV_OK) 205 pParamCopy->flags |= RMAPI_PARAM_COPY_FLAGS_SKIP_COPYOUT; 206 207 cpStatus = rmapiParamsRelease(pParamCopy); 208 if (status == NV_OK) 209 status = cpStatus; 210 } 211 212 PORT_FREE(g_resServ.pAllocator, pParamCopy); 213 214 return status; 215 } 216 217 NV_STATUS 218 serverLookupSecondClient 219 ( 220 RS_RES_ALLOC_PARAMS_INTERNAL *pParams, 221 NvHandle *phClient 222 ) 223 { 224 *phClient = 0; 225 226 switch (pParams->externalClassId) 227 { 228 case GT200_DEBUGGER: 229 { 230 NV83DE_ALLOC_PARAMETERS *pNv83deParams = pParams->pAllocParams; 231 232 if (pNv83deParams->hAppClient != pParams->hClient) 233 *phClient = pNv83deParams->hAppClient; 234 235 break; 236 } 237 case UVM_CHANNEL_RETAINER: 238 { 239 NV_UVM_CHANNEL_RETAINER_ALLOC_PARAMS *pUvmChannelRetainerParams = pParams->pAllocParams; 240 241 if (pUvmChannelRetainerParams->hClient != pParams->hClient) 242 *phClient = pUvmChannelRetainerParams->hClient; 243 244 break; 245 } 246 default: 247 break; 248 } 249 250 return NV_OK; 251 } 252 253 NV_STATUS 254 serverTopLock_Prologue 255 ( 256 RsServer *pServer, 257 LOCK_ACCESS_TYPE access, 258 RS_LOCK_INFO *pLockInfo, 259 NvU32 *pReleaseFlags 260 ) 261 { 262 OBJSYS *pSys = SYS_GET_INSTANCE(); 263 NV_STATUS status; 264 if ((pLockInfo->flags & RM_LOCK_FLAGS_RM_SEMA) && 265 !(pLockInfo->state & RM_LOCK_STATES_RM_SEMA_ACQUIRED)) 266 { 267 if ((status = osAcquireRmSema(pSys->pSema)) != NV_OK) 268 return status; 269 pLockInfo->state |= RM_LOCK_STATES_RM_SEMA_ACQUIRED; 270 *pReleaseFlags |= RM_LOCK_RELEASE_RM_SEMA; 271 } 272 273 if (!(pLockInfo->flags & RM_LOCK_FLAGS_NO_API_LOCK)) 274 { 275 if (!(pLockInfo->state & RM_LOCK_STATES_API_LOCK_ACQUIRED)) 276 { 277 NvU32 flags = RMAPI_LOCK_FLAGS_NONE; 278 if (access == LOCK_ACCESS_READ) 279 flags |= RMAPI_LOCK_FLAGS_READ; 280 281 if ((status = rmapiLockAcquire(flags, RM_LOCK_MODULES_CLIENT)) != NV_OK) 282 { 283 return status; 284 } 285 pLockInfo->state |= RM_LOCK_STATES_API_LOCK_ACQUIRED; 286 *pReleaseFlags |= RM_LOCK_RELEASE_API_LOCK; 287 } 288 else 289 { 290 if (!rmapiLockIsOwner()) 291 { 292 NV_ASSERT(0); 293 return NV_ERR_INVALID_LOCK_STATE; 294 } 295 } 296 } 297 298 return NV_OK; 299 } 300 301 void 302 serverTopLock_Epilogue 303 ( 304 RsServer *pServer, 305 LOCK_ACCESS_TYPE access, 306 RS_LOCK_INFO *pLockInfo, 307 NvU32 *pReleaseFlags 308 ) 309 { 310 OBJSYS *pSys = SYS_GET_INSTANCE(); 311 312 if (*pReleaseFlags & RM_LOCK_RELEASE_API_LOCK) 313 { 314 rmapiLockRelease(); 315 pLockInfo->state &= ~RM_LOCK_STATES_API_LOCK_ACQUIRED; 316 *pReleaseFlags &= ~RM_LOCK_RELEASE_API_LOCK; 317 } 318 319 if (*pReleaseFlags & RM_LOCK_RELEASE_RM_SEMA) 320 { 321 osReleaseRmSema(pSys->pSema, NULL); 322 pLockInfo->state &= ~RM_LOCK_STATES_RM_SEMA_ACQUIRED; 323 *pReleaseFlags &= ~RM_LOCK_RELEASE_RM_SEMA; 324 } 325 } 326 327 NV_STATUS 328 serverResLock_Prologue 329 ( 330 RsServer *pServer, 331 LOCK_ACCESS_TYPE access, 332 RS_LOCK_INFO *pLockInfo, 333 NvU32 *pReleaseFlags 334 ) 335 { 336 NV_STATUS status = NV_OK; 337 OBJGPU *pParentGpu = NULL; 338 339 if (pLockInfo->state & RM_LOCK_STATES_GPUS_LOCK_ACQUIRED) 340 { 341 if (rmGpuLockIsOwner()) 342 { 343 return NV_OK; 344 } 345 else 346 { 347 NV_ASSERT(0); 348 status = NV_ERR_INVALID_LOCK_STATE; 349 goto done; 350 } 351 } 352 353 if (!(pLockInfo->flags & RM_LOCK_FLAGS_NO_GPUS_LOCK)) 354 { 355 if (rmGpuLockIsOwner()) 356 { 357 if (!(pLockInfo->state & RM_LOCK_STATES_ALLOW_RECURSIVE_LOCKS)) 358 { 359 NV_ASSERT(0); 360 status = NV_ERR_INVALID_LOCK_STATE; 361 goto done; 362 } 363 } 364 else 365 { 366 if ((status = rmGpuLocksAcquire(API_LOCK_FLAGS_NONE, RM_LOCK_MODULES_CLIENT)) != NV_OK) 367 goto done; 368 369 *pReleaseFlags |= RM_LOCK_RELEASE_GPUS_LOCK; 370 pLockInfo->state |= RM_LOCK_STATES_GPUS_LOCK_ACQUIRED; 371 } 372 } 373 374 if (pLockInfo->flags & RM_LOCK_FLAGS_GPU_GROUP_LOCK) 375 { 376 RsResourceRef *pParentRef; 377 GpuResource *pGpuResource; 378 NvU32 gpuMask; 379 (void)gpuMask; 380 381 pParentRef = pLockInfo->pContextRef; 382 if (pParentRef == NULL) 383 { 384 NV_ASSERT(0); 385 status = NV_ERR_INVALID_OBJECT_PARENT; 386 goto done; 387 } 388 389 // 390 // Use the pGpu from parent resource as it will work on alloc & free. 391 // Everything below NV0080_DEVICE uses the same pGpu group 392 // 393 // GPU teardown paths free client resources before tearing down pGpu so 394 // pGpu should always be valid at this point. 395 // 396 pGpuResource = dynamicCast(pParentRef->pResource, GpuResource); 397 398 if (pGpuResource == NULL) 399 { 400 // 401 // If parent is not a GpuResource, we might still be a NV0080_DEVICE 402 // so check and handle that case before reporting an error.. 403 // 404 CALL_CONTEXT *pCallContext = resservGetTlsCallContext(); 405 if (pCallContext != NULL && pCallContext->pResourceRef != NULL) 406 { 407 pGpuResource = dynamicCast(pCallContext->pResourceRef->pResource, GpuResource); 408 } 409 if (pGpuResource == NULL) 410 { 411 NV_ASSERT_FAILED("Attempting to lock per-GPU lock for a non-GpuResource"); 412 status = NV_ERR_INVALID_OBJECT_PARENT; 413 goto done; 414 } 415 } 416 417 pParentGpu = GPU_RES_GET_GPU(pGpuResource); 418 419 if (pLockInfo->state & RM_LOCK_STATES_GPU_GROUP_LOCK_ACQUIRED) 420 { 421 if (rmGpuGroupLockIsOwner(pParentGpu->gpuInstance, GPU_LOCK_GRP_DEVICE, &gpuMask)) 422 { 423 goto done; 424 } 425 else 426 { 427 NV_ASSERT(0); 428 status = NV_ERR_INVALID_LOCK_STATE; 429 goto done; 430 } 431 } 432 433 if (rmGpuGroupLockIsOwner(pParentGpu->gpuInstance, GPU_LOCK_GRP_DEVICE, &gpuMask)) 434 { 435 if (!(pLockInfo->state & RM_LOCK_STATES_ALLOW_RECURSIVE_LOCKS)) 436 { 437 NV_ASSERT(0); 438 status = NV_ERR_INVALID_LOCK_STATE; 439 goto done; 440 } 441 } 442 else 443 { 444 status = rmGpuGroupLockAcquire(pParentGpu->gpuInstance, 445 GPU_LOCK_GRP_DEVICE, 446 GPUS_LOCK_FLAGS_NONE, 447 RM_LOCK_MODULES_CLIENT, 448 &pLockInfo->gpuMask); 449 if (status != NV_OK) 450 goto done; 451 452 *pReleaseFlags |= RM_LOCK_RELEASE_GPU_GROUP_LOCK; 453 pLockInfo->state |= RM_LOCK_STATES_GPU_GROUP_LOCK_ACQUIRED; 454 } 455 } 456 457 done: 458 switch(pLockInfo->traceOp) 459 { 460 case RS_LOCK_TRACE_ALLOC: 461 LOCK_METER_DATA(ALLOC, pLockInfo->traceClassId, 0, 0); 462 break; 463 case RS_LOCK_TRACE_FREE: 464 LOCK_METER_DATA(FREE_OBJECT, pLockInfo->traceClassId, 0, 0); 465 break; 466 case RS_LOCK_TRACE_CTRL: 467 LOCK_METER_DATA(RMCTRL, pLockInfo->traceClassId, pLockInfo->flags, status); 468 break; 469 default: 470 break; 471 } 472 473 return status; 474 } 475 476 NV_STATUS 477 serverAllocEpilogue_WAR 478 ( 479 RsServer *pServer, 480 NV_STATUS status, 481 NvBool bClientAlloc, 482 RS_RES_ALLOC_PARAMS_INTERNAL *pRmAllocParams 483 ) 484 { 485 // 486 // Pre-Volta Linux swapgroups is the only remaining use of channel grabbing. 487 // Bug 2869820 is tracking the transition of swapgroups from requiring this 488 // RM feature. 489 // 490 NV_STATUS tmpStatus; 491 if (!bClientAlloc && status == NV_ERR_INSERT_DUPLICATE_NAME) 492 { 493 NvBool gpulockRelease = NV_FALSE; 494 RsResourceRef *pResourceRef; 495 496 if (!rmGpuLockIsOwner()) 497 { 498 tmpStatus = rmGpuLocksAcquire(GPUS_LOCK_FLAGS_NONE, 499 RM_LOCK_MODULES_CLIENT); 500 501 if (tmpStatus != NV_OK) 502 return tmpStatus; 503 504 gpulockRelease = NV_TRUE; 505 } 506 507 // 508 // Hack for taking ownership of display channels. Clients call rmAlloc 509 // on a previously allocated handle to indicate they want to grab 510 // ownership of the underlying hardware channel. 511 // 512 // TODO - this should be moved to an RM control and called directly by 513 // clients instead of the overloaded allocation call. RmAlloc should 514 // be for allocating objects only. 515 // 516 tmpStatus = clientGetResourceRef(pRmAllocParams->pClient, pRmAllocParams->hResource, &pResourceRef); 517 if (tmpStatus == NV_OK) 518 { 519 DispChannel *pDispChannel = dynamicCast(pResourceRef->pResource, DispChannel); 520 if (pDispChannel != NULL) 521 { 522 status = dispchnGrabChannel(pDispChannel, 523 pRmAllocParams->hClient, 524 pRmAllocParams->hParent, 525 pRmAllocParams->hResource, 526 pRmAllocParams->externalClassId, 527 pRmAllocParams->pAllocParams); 528 } 529 } 530 531 if (gpulockRelease) 532 rmGpuLocksRelease(GPUS_LOCK_FLAGS_NONE, NULL); 533 } 534 535 return status; 536 } 537 538 static NV_STATUS 539 _rmAlloc 540 ( 541 NvHandle hClient, 542 NvHandle hParent, 543 NvHandle *phObject, 544 NvU32 hClass, 545 NvP64 pUserAllocParams, 546 NvU32 allocFlags, 547 NvU32 allocInitStates, 548 RS_LOCK_INFO *pLockInfo, 549 NvP64 pRightsRequested, 550 API_SECURITY_INFO secInfo 551 ) 552 { 553 NV_STATUS status; 554 RS_RES_ALLOC_PARAMS_INTERNAL rmAllocParams = {0}; 555 556 NV_ASSERT_OR_RETURN(phObject != NULL, NV_ERR_INVALID_ARGUMENT); 557 558 // init RmAllocParams 559 rmAllocParams.hClient = hClient; 560 rmAllocParams.hParent = hParent; 561 rmAllocParams.hResource = *phObject; 562 rmAllocParams.externalClassId = hClass; 563 rmAllocParams.allocFlags = allocFlags; 564 rmAllocParams.allocState = allocInitStates; 565 rmAllocParams.pSecInfo = &secInfo; 566 rmAllocParams.pResourceRef = NULL; 567 rmAllocParams.pAllocParams = NvP64_VALUE(pUserAllocParams); 568 rmAllocParams.pLockInfo = pLockInfo; 569 rmAllocParams.pRightsRequested = NvP64_VALUE(pRightsRequested); 570 rmAllocParams.pRightsRequired = NULL; 571 572 status = serverAllocResource(&g_resServ, &rmAllocParams); 573 *phObject = rmAllocParams.hResource; 574 575 return status; 576 577 } 578 579 static 580 NV_STATUS 581 _fixupAllocParams 582 ( 583 RS_RESOURCE_DESC **ppResDesc, 584 RS_RES_ALLOC_PARAMS_INTERNAL *pRmAllocParams 585 ) 586 { 587 RS_RESOURCE_DESC *pResDesc = *ppResDesc; 588 589 if ((pResDesc->pClassInfo != NULL) && (pResDesc->pClassInfo->classId == classId(Event))) 590 { 591 NV0005_ALLOC_PARAMETERS *pNv0005Params = pRmAllocParams->pAllocParams; 592 593 // 594 // This field isn't filled out consistently by clients. Some clients specify NV01_EVENT as the class 595 // and then override it using the subclass in the event parameters, while other clients specify the 596 // same subclass in both the RmAllocParams and event params. NV01_EVENT isn't a valid class to allocate 597 // so overwrite it with the subclass from the event params. 598 // 599 if (pRmAllocParams->externalClassId == NV01_EVENT) 600 pRmAllocParams->externalClassId = pNv0005Params->hClass; 601 602 pNv0005Params->hSrcResource = pRmAllocParams->hParent; 603 604 // No support for event and src resource that reside under different clients 605 if (pNv0005Params->hParentClient != pRmAllocParams->hClient) 606 pRmAllocParams->hParent = pRmAllocParams->hClient; 607 608 // class id may have changed so refresh the resource descriptor, but make sure it is still an Event 609 pResDesc = RsResInfoByExternalClassId(pRmAllocParams->externalClassId); 610 if (pResDesc == NULL || pResDesc->pClassInfo == NULL || pResDesc->pClassInfo->classId != classId(Event)) 611 return NV_ERR_INVALID_CLASS; 612 613 *ppResDesc = pResDesc; 614 } 615 616 return NV_OK; 617 } 618 619 NV_STATUS 620 serverAllocResourceUnderLock 621 ( 622 RsServer *pServer, 623 RS_RES_ALLOC_PARAMS *pRmAllocParams 624 ) 625 { 626 NvHandle hClient = pRmAllocParams->hClient; 627 NvHandle hParent; 628 RS_RESOURCE_DESC *pResDesc; 629 NV_STATUS status = NV_OK; 630 NV_STATUS tmpStatus; 631 RsClient *pClient = pRmAllocParams->pClient; 632 RsResourceRef *pParentRef = NULL; 633 RsResourceRef *pResourceRef = NULL; 634 NvU32 i = 0; 635 RS_LOCK_INFO *pLockInfo = pRmAllocParams->pLockInfo; 636 NvU32 releaseFlags = 0; 637 RS_ACCESS_MASK rightsRequired; 638 LOCK_ACCESS_TYPE resLockAccess = LOCK_ACCESS_WRITE; 639 OBJGPU *pGpu = NULL; 640 NvBool bClearRecursiveStateFlag = NV_FALSE; 641 642 if (!pServer->bConstructed) 643 return NV_ERR_NOT_READY; 644 645 if (pRmAllocParams->pSecInfo == NULL) 646 { 647 return NV_ERR_INVALID_ARGUMENT; 648 } 649 650 pResDesc = RsResInfoByExternalClassId(pRmAllocParams->externalClassId); 651 if (pResDesc == NULL) 652 { 653 return NV_ERR_INVALID_CLASS; 654 } 655 656 NV_ASSERT_OK_OR_RETURN(_fixupAllocParams(&pResDesc, pRmAllocParams)); 657 rmapiResourceDescToLegacyFlags(pResDesc, &pLockInfo->flags, NULL); 658 659 pLockInfo->traceOp = RS_LOCK_TRACE_ALLOC; 660 pLockInfo->traceClassId = pRmAllocParams->externalClassId; 661 hParent = pRmAllocParams->hParent; 662 if (pRmAllocParams->hResource == hClient) 663 { 664 if (pResDesc->pParentList[i] != 0) 665 status = NV_ERR_INVALID_OBJECT_PARENT; 666 hParent = 0; 667 668 // Single instance restriction is implied 669 NV_ASSERT(!pResDesc->bMultiInstance); 670 } 671 else 672 { 673 // Check if parent is valid 674 status = clientGetResourceRef(pClient, hParent, &pParentRef); 675 if (status != NV_OK) 676 { 677 goto done; 678 } 679 pLockInfo->pContextRef = pParentRef; 680 } 681 682 if ((pResDesc->flags & RS_FLAGS_INTERNAL_ONLY) && 683 !(pRmAllocParams->allocState & RM_ALLOC_STATES_INTERNAL_ALLOC)) 684 { 685 status = NV_ERR_INVALID_CLASS; 686 goto done; 687 } 688 689 status = serverAllocResourceLookupLockFlags(&g_resServ, RS_LOCK_RESOURCE, pRmAllocParams, &resLockAccess); 690 if (status != NV_OK) 691 goto done; 692 693 // 694 // We can get the GPU pointer for alloc of a device child. 695 // Device allocs need to be handled separately. See deviceInit_IMPL() 696 // 697 tmpStatus = gpuGetByRef(pParentRef, NULL, &pGpu); 698 699 // Override locking flags if we'll need to RPC to GSP 700 if (pGpu != NULL && IS_GSP_CLIENT(pGpu) && 701 (pResDesc->flags & RS_FLAGS_ALLOC_RPC_TO_PHYS_RM)) 702 { 703 resLockAccess = LOCK_ACCESS_WRITE; // always write as we're RPCing to GSP 704 705 // 706 // If the resource desc says no need for GPU locks, we still need to lock 707 // the current pGpu in order to send the RPC 708 // 709 if (pLockInfo->flags & RM_LOCK_FLAGS_NO_GPUS_LOCK) 710 { 711 NV_PRINTF(LEVEL_INFO, "Overriding flags for alloc of class %04x\n", 712 pRmAllocParams->externalClassId); 713 pLockInfo->flags &= ~RM_LOCK_FLAGS_NO_GPUS_LOCK; 714 pLockInfo->flags |= RM_LOCK_FLAGS_GPU_GROUP_LOCK; 715 if ((pLockInfo->state & RM_LOCK_STATES_ALLOW_RECURSIVE_LOCKS) == 0) 716 { 717 pLockInfo->state |= RM_LOCK_STATES_ALLOW_RECURSIVE_LOCKS; 718 bClearRecursiveStateFlag = NV_TRUE; 719 } 720 } 721 } 722 723 status = serverResLock_Prologue(&g_resServ, resLockAccess, pLockInfo, &releaseFlags); 724 if (status != NV_OK) 725 goto done; 726 727 if (pParentRef != NULL) 728 { 729 // 730 // Check if GPU in fatal condition. 731 // 732 if (pGpu != NULL) 733 { 734 // 735 // Abort if any GPU in SLI has fatal error. 736 // This property will be cleared on RM init, by which time the 737 // client should have reset the GPUs. 738 // 739 SLI_LOOP_START(SLI_LOOP_FLAGS_BC_ONLY | 740 SLI_LOOP_FLAGS_IGNORE_REENTRANCY) 741 { 742 if (pGpu->getProperty(pGpu, PDB_PROP_GPU_IN_FATAL_ERROR)) 743 { 744 KernelRc *pKernelRc = GPU_GET_KERNEL_RC(pGpu); 745 if (pKernelRc != NULL) 746 { 747 krcBreakpoint(pKernelRc); 748 } 749 status = NV_ERR_RESET_REQUIRED; 750 SLI_LOOP_GOTO(done); 751 } 752 } 753 SLI_LOOP_END; 754 } 755 756 // If single instance, ensure parent doesn't yet have a class of this type 757 if (!pResDesc->bMultiInstance) 758 { 759 if (refFindChildOfType(pParentRef, pResDesc->pClassInfo->classId, NV_TRUE, NULL) == NV_OK) 760 { 761 status = NV_ERR_STATE_IN_USE; 762 } 763 } 764 765 // Check if hParent is an allowed parent for this resource 766 if (status == NV_OK && !pResDesc->bAnyParent) 767 { 768 status = NV_ERR_INVALID_OBJECT_PARENT; 769 for (i = 0; pResDesc->pParentList[i]; i++) 770 { 771 if (pParentRef->internalClassId == pResDesc->pParentList[i]) 772 { 773 status = NV_OK; 774 break; 775 } 776 } 777 } 778 } 779 780 if (status != NV_OK) 781 goto done; 782 783 status = clientAssignResourceHandle(pClient, &pRmAllocParams->hResource); 784 if (status != NV_OK) 785 goto done; 786 787 pRmAllocParams->hParent = (pRmAllocParams->hParent == 0) ? pRmAllocParams->hClient : pRmAllocParams->hParent; 788 789 if (pServer->bRsAccessEnabled) 790 { 791 rsAccessMaskFromArray(&rightsRequired, pResDesc->pRightsRequiredArray, 792 pResDesc->rightsRequiredLength); 793 pRmAllocParams->pRightsRequired = &rightsRequired; 794 } 795 796 status = clientAllocResource(pClient, &g_resServ, pRmAllocParams); 797 if (status != NV_OK) 798 goto done; 799 800 pResourceRef = pRmAllocParams->pResourceRef; 801 802 // 803 // Alloc RPC handling 804 // 805 if (!(pRmAllocParams->allocState & RM_ALLOC_STATES_SKIP_RPC)) 806 { 807 if (pResDesc->flags & (RS_FLAGS_ALLOC_RPC_TO_VGPU_HOST | RS_FLAGS_ALLOC_RPC_TO_PHYS_RM)) 808 { 809 OBJGPU *pGpu = NULL; 810 RmResource *pRmResource = dynamicCast(pResourceRef->pResource, RmResource); 811 CALL_CONTEXT callContext = {0}; 812 CALL_CONTEXT *pOldContext = NULL; 813 814 status = gpuGetByRef(pResourceRef, NULL, &pGpu); 815 if (status != NV_OK || pRmResource == NULL) 816 { 817 status = NV_ERR_INVALID_CLASS; 818 goto done; 819 } 820 821 if (!IS_VIRTUAL(pGpu) && !IS_GSP_CLIENT(pGpu)) 822 { 823 status = NV_OK; 824 goto done; 825 } 826 827 // if physical RM RPC make sure we're a GSP client otherwise skip 828 if (((pResDesc->flags & (RS_FLAGS_ALLOC_RPC_TO_VGPU_HOST | RS_FLAGS_ALLOC_RPC_TO_PHYS_RM)) == RS_FLAGS_ALLOC_RPC_TO_PHYS_RM) && 829 (!IS_GSP_CLIENT(pGpu))) 830 { 831 status = NV_OK; 832 goto done; 833 } 834 835 // Set the call context to allow vgpuGetCallingContextDevice() 836 // and other context dependent functions to operate in the RPC code. 837 // 838 // The context is assigned in the above clientAllocResource() call, 839 // but we can't simply extend the context scope to this place 840 // as pResourceRef is allocated internally in clientAllocResource(). 841 // 842 // Instead, we create basically the same context here once again 843 // and use it for the RPC call. 844 callContext.pServer = pServer; 845 callContext.pClient = pClient; 846 callContext.pResourceRef = pResourceRef; 847 callContext.pLockInfo = pRmAllocParams->pLockInfo; 848 callContext.secInfo = *pRmAllocParams->pSecInfo; 849 850 resservSwapTlsCallContext(&pOldContext, &callContext); 851 NV_RM_RPC_ALLOC_OBJECT(pGpu, 852 pRmAllocParams->hClient, 853 pRmAllocParams->hParent, 854 pRmAllocParams->hResource, 855 pRmAllocParams->externalClassId, 856 pRmAllocParams->pAllocParams, 857 status); 858 resservRestoreTlsCallContext(pOldContext); 859 860 if (status != NV_OK) 861 goto done; 862 863 pRmResource->bRpcFree = NV_TRUE; 864 } 865 } 866 867 done: 868 if ((status != NV_OK) && (pResourceRef != NULL)) 869 { 870 RS_RES_FREE_PARAMS params; 871 872 portMemSet(¶ms, 0, sizeof(params)); 873 params.hClient = hClient; 874 params.hResource = pRmAllocParams->hResource; 875 params.pResourceRef = pResourceRef; 876 params.pSecInfo = pRmAllocParams->pSecInfo; 877 params.pLockInfo = pRmAllocParams->pLockInfo; 878 tmpStatus = clientFreeResource(pClient, &g_resServ, ¶ms); 879 NV_ASSERT(tmpStatus == NV_OK); 880 pRmAllocParams->pResourceRef = NULL; 881 } 882 883 serverResLock_Epilogue(&g_resServ, resLockAccess, pLockInfo, &releaseFlags); 884 885 if (bClearRecursiveStateFlag) 886 { 887 pLockInfo->state &= ~RM_LOCK_STATES_ALLOW_RECURSIVE_LOCKS; 888 } 889 return status; 890 } 891 892 NV_STATUS 893 serverFreeResourceRpcUnderLock 894 ( 895 RsServer *pServer, 896 RS_RES_FREE_PARAMS *pFreeParams 897 ) 898 { 899 NV_STATUS status; 900 RsResourceRef *pResourceRef = pFreeParams->pResourceRef; 901 OBJGPU *pGpu = NULL; 902 NvBool bBcResource; 903 RmResource *pRmResource = NULL; 904 905 NV_ASSERT_OR_RETURN(pResourceRef != NULL, NV_ERR_INVALID_OBJECT_HANDLE); 906 907 pRmResource = dynamicCast(pResourceRef->pResource, RmResource); 908 status = gpuGetByRef(pResourceRef, &bBcResource, &pGpu); 909 if ((status != NV_OK) || 910 (!IS_VIRTUAL(pGpu) && !IS_GSP_CLIENT(pGpu)) || 911 (pRmResource == NULL) || 912 (pRmResource->bRpcFree == NV_FALSE)) 913 { 914 status = NV_OK; 915 goto rpc_done; 916 } 917 918 gpuSetThreadBcState(pGpu, bBcResource); 919 NV_RM_RPC_FREE(pGpu, pResourceRef->pClient->hClient, 920 pResourceRef->pParentRef->hResource, 921 pResourceRef->hResource, status); 922 923 rpc_done: 924 return status; 925 } 926 927 void 928 serverResLock_Epilogue 929 ( 930 RsServer *pServer, 931 LOCK_ACCESS_TYPE access, 932 RS_LOCK_INFO *pLockInfo, 933 NvU32 *pReleaseFlags 934 ) 935 { 936 NvU32 gpuLockFlags = GPUS_LOCK_FLAGS_NONE; 937 if (access == LOCK_ACCESS_READ) 938 gpuLockFlags |= GPU_LOCK_FLAGS_READ; 939 940 if (*pReleaseFlags & RM_LOCK_RELEASE_GPU_GROUP_LOCK) 941 { 942 // UNLOCK: release GPU group lock 943 rmGpuGroupLockRelease(pLockInfo->gpuMask, GPUS_LOCK_FLAGS_NONE); 944 pLockInfo->state &= ~RM_LOCK_STATES_GPU_GROUP_LOCK_ACQUIRED; 945 *pReleaseFlags &= ~RM_LOCK_RELEASE_GPU_GROUP_LOCK; 946 } 947 948 if (*pReleaseFlags & RM_LOCK_RELEASE_GPUS_LOCK) 949 { 950 // UNLOCK: release GPUs lock 951 rmGpuLocksRelease(GPUS_LOCK_FLAGS_NONE, NULL); 952 pLockInfo->state &= ~RM_LOCK_STATES_GPUS_LOCK_ACQUIRED; 953 *pReleaseFlags &= ~RM_LOCK_RELEASE_GPUS_LOCK; 954 } 955 } 956 957 NV_STATUS 958 serverInitFreeParams_Recursive(NvHandle hClient, NvHandle hResource, RS_LOCK_INFO *pLockInfo, RS_RES_FREE_PARAMS *pParams) 959 { 960 portMemSet(pParams, 0, sizeof(*pParams)); 961 pParams->hClient = hClient; 962 pParams->hResource = hResource; 963 pParams->pLockInfo = pLockInfo; 964 return NV_OK; 965 } 966 967 NV_STATUS 968 serverUpdateLockFlagsForFree 969 ( 970 RsServer *pServer, 971 RS_RES_FREE_PARAMS_INTERNAL *pRmFreeParams 972 ) 973 { 974 RS_LOCK_INFO *pLockInfo = pRmFreeParams->pLockInfo; 975 OBJGPU *pGpu = NULL; 976 977 rmapiResourceDescToLegacyFlags(pRmFreeParams->pResourceRef->pResourceDesc, NULL, &pLockInfo->flags); 978 979 pLockInfo->pContextRef = pRmFreeParams->pResourceRef->pParentRef; 980 if (gpuGetByRef(pLockInfo->pContextRef, NULL, &pGpu) == NV_OK) 981 { 982 RmResource *pRmResource = dynamicCast(pRmFreeParams->pResourceRef->pResource, RmResource); 983 if (pGpu != NULL && IS_GSP_CLIENT(pGpu) && pRmResource != NULL && pRmResource->bRpcFree) 984 { 985 // 986 // If the resource desc says no need for GPU locks, we still need to lock 987 // the current pGpu in order to send the RPC 988 // 989 if (pLockInfo->flags & RM_LOCK_FLAGS_NO_GPUS_LOCK) 990 { 991 NV_PRINTF(LEVEL_INFO, "Overriding flags for free of class %04x\n", 992 pRmFreeParams->pResourceRef->externalClassId); 993 pLockInfo->flags &= ~RM_LOCK_FLAGS_NO_GPUS_LOCK; 994 pLockInfo->flags |= RM_LOCK_FLAGS_GPU_GROUP_LOCK; 995 pLockInfo->state |= RM_LOCK_STATES_ALLOW_RECURSIVE_LOCKS; 996 } 997 } 998 } 999 1000 return NV_OK; 1001 } 1002 1003 NV_STATUS 1004 rmapiFreeResourcePrologue 1005 ( 1006 RS_RES_FREE_PARAMS_INTERNAL *pRmFreeParams 1007 ) 1008 { 1009 RsResourceRef *pResourceRef = pRmFreeParams->pResourceRef; 1010 NV_STATUS tmpStatus; 1011 OBJGPU *pGpu = NULL; 1012 NvBool bBcResource; 1013 1014 NV_ASSERT_OR_RETURN(pResourceRef, NV_ERR_INVALID_OBJECT_HANDLE); 1015 1016 // 1017 // Use gpuGetByRef instead of GpuResource because gpuGetByRef will work even 1018 // if resource isn't a GpuResource (e.g.: Memory which can be allocated 1019 // under a subdevice, device or client root) 1020 // 1021 tmpStatus = gpuGetByRef(pResourceRef, &bBcResource, &pGpu); 1022 if (tmpStatus == NV_OK) 1023 gpuSetThreadBcState(pGpu, bBcResource); 1024 1025 // 1026 // Need to cancel pending timer callbacks before event structs are freed. 1027 // RS-TODO: provide notifications to objects referencing events or add 1028 // dependency 1029 // 1030 TimerApi *pTimerApi = dynamicCast(pResourceRef->pResource, TimerApi); 1031 if (pTimerApi != NULL) 1032 { 1033 tmrapiDeregisterEvents(pTimerApi); 1034 } 1035 1036 CliDelObjectEvents(pRmFreeParams->hClient, pRmFreeParams->hResource); 1037 1038 return NV_OK; 1039 } 1040 1041 NV_STATUS 1042 rmapiAlloc 1043 ( 1044 RM_API *pRmApi, 1045 NvHandle hClient, 1046 NvHandle hParent, 1047 NvHandle *phObject, 1048 NvU32 hClass, 1049 void *pAllocParams 1050 ) 1051 { 1052 if (!pRmApi->bHasDefaultSecInfo) 1053 return NV_ERR_NOT_SUPPORTED; 1054 1055 return pRmApi->AllocWithSecInfo(pRmApi, hClient, hParent, phObject, hClass, NV_PTR_TO_NvP64(pAllocParams), 1056 RMAPI_ALLOC_FLAGS_NONE, NvP64_NULL, &pRmApi->defaultSecInfo); 1057 } 1058 1059 NV_STATUS 1060 rmapiAllocWithHandle 1061 ( 1062 RM_API *pRmApi, 1063 NvHandle hClient, 1064 NvHandle hParent, 1065 NvHandle hObject, 1066 NvU32 hClass, 1067 void *pAllocParams 1068 ) 1069 { 1070 if (!pRmApi->bHasDefaultSecInfo) 1071 return NV_ERR_NOT_SUPPORTED; 1072 1073 return pRmApi->AllocWithSecInfo(pRmApi, hClient, hParent, &hObject, hClass, NV_PTR_TO_NvP64(pAllocParams), 1074 RMAPI_ALLOC_FLAGS_NONE, NvP64_NULL, &pRmApi->defaultSecInfo); 1075 } 1076 1077 NV_STATUS 1078 rmapiAllocWithSecInfo 1079 ( 1080 RM_API *pRmApi, 1081 NvHandle hClient, 1082 NvHandle hParent, 1083 NvHandle *phObject, 1084 NvU32 hClass, 1085 NvP64 pAllocParams, 1086 NvU32 flags, 1087 NvP64 pRightsRequested, 1088 API_SECURITY_INFO *pSecInfo 1089 ) 1090 { 1091 NV_STATUS status; 1092 NvU32 allocInitStates = RM_ALLOC_STATES_NONE; 1093 RM_API_CONTEXT rmApiContext = {0}; 1094 RS_LOCK_INFO *pLockInfo; 1095 1096 status = rmapiPrologue(pRmApi, &rmApiContext); 1097 if (status != NV_OK) 1098 return status; 1099 1100 pLockInfo = portMemAllocNonPaged(sizeof(*pLockInfo)); 1101 if (pLockInfo == NULL) 1102 { 1103 status = NV_ERR_NO_MEMORY; 1104 goto done; 1105 } 1106 1107 portMemSet(pLockInfo, 0, sizeof(*pLockInfo)); 1108 rmapiInitLockInfo(pRmApi, hClient, pLockInfo); 1109 1110 // RS-TODO: Fix calls that use RMAPI_GPU_LOCK_INTERNAL without holding the API lock 1111 if (pRmApi->bGpuLockInternal && !rmapiLockIsOwner()) 1112 { 1113 NV_PRINTF(LEVEL_ERROR, "RMAPI_GPU_LOCK_INTERNAL alloc requested without holding the RMAPI lock\n"); 1114 pLockInfo->flags |= RM_LOCK_FLAGS_NO_API_LOCK; 1115 pLockInfo->state &= ~RM_LOCK_STATES_API_LOCK_ACQUIRED; 1116 } 1117 1118 // This flag applies to both VGPU and GSP cases 1119 if (flags & RMAPI_ALLOC_FLAGS_SKIP_RPC) 1120 allocInitStates |= RM_ALLOC_STATES_SKIP_RPC; 1121 1122 // 1123 // Mark internal client allocations as such, so the resource server generates 1124 // the internal client handle with a distinct template. 1125 // The distinct template purpose is to make sure that GSP client provided 1126 // client handles do not collide with the client handles ganerated by the GSP/FW RM. 1127 // 1128 if ((pSecInfo->privLevel >= RS_PRIV_LEVEL_KERNEL) && 1129 (pSecInfo->paramLocation == PARAM_LOCATION_KERNEL) && pRmApi->bGpuLockInternal) 1130 allocInitStates |= RM_ALLOC_STATES_INTERNAL_CLIENT_HANDLE; 1131 1132 if ((pSecInfo->paramLocation == PARAM_LOCATION_KERNEL) && 1133 (pRmApi->bApiLockInternal || pRmApi->bGpuLockInternal)) 1134 allocInitStates |= RM_ALLOC_STATES_INTERNAL_ALLOC; 1135 1136 NV_PRINTF(LEVEL_INFO, "client:0x%x parent:0x%x object:0x%x class:0x%x\n", 1137 hClient, hParent, *phObject, hClass); 1138 1139 status = _rmAlloc(hClient, 1140 hParent, 1141 phObject, 1142 hClass, 1143 pAllocParams, 1144 flags, 1145 allocInitStates, 1146 pLockInfo, 1147 pRightsRequested, 1148 *pSecInfo); 1149 1150 1151 // 1152 // If hClient is allocated behind GPU locks, client is marked as internal 1153 // 1154 if ((status == NV_OK) && ((hClass == NV01_ROOT) || (hClass == NV01_ROOT_NON_PRIV) || (hClass == NV01_ROOT_CLIENT)) && 1155 pSecInfo->paramLocation == PARAM_LOCATION_KERNEL && pRmApi->bGpuLockInternal) 1156 { 1157 void *pHClient = *(void **)&pAllocParams; 1158 1159 // flag this client as an RM internal client 1160 rmclientSetClientFlagsByHandle(*(NvU32*)pHClient /* hClient */, RMAPI_CLIENT_FLAG_RM_INTERNAL_CLIENT); 1161 } 1162 1163 if (status == NV_OK) 1164 { 1165 NV_PRINTF(LEVEL_INFO, "allocation complete\n"); 1166 } 1167 else 1168 { 1169 NV_PRINTF(LEVEL_WARNING, "allocation failed; status: %s (0x%08x)\n", 1170 nvstatusToString(status), status); 1171 NV_PRINTF(LEVEL_WARNING, 1172 "client:0x%x parent:0x%x object:0x%x class:0x%x\n", hClient, 1173 hParent, *phObject, hClass); 1174 } 1175 1176 portMemFree(pLockInfo); 1177 1178 done: 1179 rmapiEpilogue(pRmApi, &rmApiContext); 1180 1181 return status; 1182 } 1183 1184 NV_STATUS 1185 resservClientFactory 1186 ( 1187 PORT_MEM_ALLOCATOR *pAllocator, 1188 RS_RES_ALLOC_PARAMS *pParams, 1189 RsClient **ppRsClient 1190 ) 1191 { 1192 RmClient *pClient; 1193 NV_STATUS status; 1194 1195 status = objCreate(&pClient, NVOC_NULL_OBJECT, RmClient, pAllocator, pParams); 1196 1197 if (status != NV_OK) 1198 { 1199 return status; 1200 } 1201 NV_ASSERT(pClient != NULL); 1202 1203 *ppRsClient = staticCast(pClient, RsClient); 1204 return NV_OK; 1205 } 1206 1207 NV_STATUS 1208 resservResourceFactory 1209 ( 1210 PORT_MEM_ALLOCATOR *pAllocator, 1211 CALL_CONTEXT *pCallContext, 1212 RS_RES_ALLOC_PARAMS *pParams, 1213 RsResource **ppResource 1214 ) 1215 { 1216 RS_RESOURCE_DESC *pResDesc; 1217 NV_STATUS status; 1218 Dynamic *pDynamic = NULL; 1219 RsResource *pResource = NULL; 1220 OBJGPU *pGpu = NULL; 1221 1222 pResDesc = RsResInfoByExternalClassId(pParams->externalClassId); 1223 if (pResDesc == NULL) 1224 return NV_ERR_INVALID_CLASS; 1225 1226 if (pCallContext->pResourceRef->pParentRef != NULL && 1227 pCallContext->pResourceRef->pParentRef->pResource != NULL) 1228 { 1229 GpuResource *pParentGpuResource = dynamicCast(pCallContext->pResourceRef->pParentRef->pResource, 1230 GpuResource); 1231 if (pParentGpuResource != NULL) 1232 { 1233 pGpu = GPU_RES_GET_GPU(pParentGpuResource); 1234 } 1235 } 1236 1237 status = objCreateDynamicWithFlags(&pDynamic, 1238 (Object*)pGpu, 1239 pResDesc->pClassInfo, 1240 NVOC_OBJ_CREATE_FLAGS_PARENT_HALSPEC_ONLY, 1241 pCallContext, 1242 pParams); 1243 if (status != NV_OK) 1244 return status; 1245 1246 pResource = dynamicCast(pDynamic, RsResource); 1247 1248 if (pResource == NULL) 1249 return NV_ERR_INSUFFICIENT_RESOURCES; 1250 1251 if (pResDesc->internalClassId == classId(Subdevice) || pResDesc->internalClassId == classId(Device)) 1252 { 1253 pGpu = GPU_RES_GET_GPU(dynamicCast(pDynamic, GpuResource)); 1254 1255 if (pGpu && !IS_MIG_IN_USE(pGpu)) 1256 { 1257 rmapiControlCacheSetGpuInstForObject(pParams->hClient, pParams->hResource, pGpu->gpuInstance); 1258 } 1259 } 1260 1261 *ppResource = pResource; 1262 1263 return status; 1264 } 1265 1266 NV_STATUS 1267 rmapiAllocWithSecInfoTls 1268 ( 1269 RM_API *pRmApi, 1270 NvHandle hClient, 1271 NvHandle hParent, 1272 NvHandle *phObject, 1273 NvU32 hClass, 1274 NvP64 pAllocParams, 1275 NvU32 flags, 1276 NvP64 pRightsRequested, 1277 API_SECURITY_INFO *pSecInfo 1278 ) 1279 { 1280 THREAD_STATE_NODE threadState; 1281 NV_STATUS status; 1282 1283 threadStateInit(&threadState, THREAD_STATE_FLAGS_NONE); 1284 1285 status = rmapiAllocWithSecInfo(pRmApi, hClient, hParent, phObject, hClass, 1286 pAllocParams, flags, pRightsRequested, pSecInfo); 1287 1288 threadStateFree(&threadState, THREAD_STATE_FLAGS_NONE); 1289 1290 return status; 1291 } 1292 1293 NV_STATUS 1294 rmapiFree 1295 ( 1296 RM_API *pRmApi, 1297 NvHandle hClient, 1298 NvHandle hObject 1299 ) 1300 { 1301 if (!pRmApi->bHasDefaultSecInfo) 1302 return NV_ERR_NOT_SUPPORTED; 1303 1304 return pRmApi->FreeWithSecInfo(pRmApi, hClient, hObject, RMAPI_FREE_FLAGS_NONE, &pRmApi->defaultSecInfo); 1305 } 1306 1307 NV_STATUS 1308 rmapiFreeWithSecInfo 1309 ( 1310 RM_API *pRmApi, 1311 NvHandle hClient, 1312 NvHandle hObject, 1313 NvU32 flags, 1314 API_SECURITY_INFO *pSecInfo 1315 ) 1316 { 1317 NV_STATUS status; 1318 RS_RES_FREE_PARAMS freeParams; 1319 RS_LOCK_INFO lockInfo; 1320 RM_API_CONTEXT rmApiContext = {0}; 1321 1322 portMemSet(&freeParams, 0, sizeof(freeParams)); 1323 1324 NV_PRINTF(LEVEL_INFO, "Nv01Free: client:0x%x object:0x%x\n", hClient, 1325 hObject); 1326 1327 status = rmapiPrologue(pRmApi, &rmApiContext); 1328 1329 if (status != NV_OK) 1330 return status; 1331 1332 portMemSet(&lockInfo, 0, sizeof(lockInfo)); 1333 rmapiInitLockInfo(pRmApi, hClient, &lockInfo); 1334 1335 // RS-TODO: Fix calls that use RMAPI_GPU_LOCK_INTERNAL without holding the API lock 1336 if (pRmApi->bGpuLockInternal && !rmapiLockIsOwner()) 1337 { 1338 NV_PRINTF(LEVEL_ERROR, "RMAPI_GPU_LOCK_INTERNAL free requested without holding the RMAPI lock\n"); 1339 lockInfo.flags |= RM_LOCK_FLAGS_NO_API_LOCK; 1340 lockInfo.state &= ~RM_LOCK_STATES_API_LOCK_ACQUIRED; 1341 } 1342 1343 freeParams.hClient = hClient; 1344 freeParams.hResource = hObject; 1345 freeParams.freeState = RM_FREE_STATES_NONE; 1346 freeParams.pLockInfo = &lockInfo; 1347 freeParams.freeFlags = flags; 1348 freeParams.pSecInfo = pSecInfo; 1349 1350 rmapiControlCacheFreeObjectEntry(hClient, hObject); 1351 1352 status = serverFreeResourceTree(&g_resServ, &freeParams); 1353 1354 rmapiEpilogue(pRmApi, &rmApiContext); 1355 1356 if (status == NV_OK) 1357 { 1358 NV_PRINTF(LEVEL_INFO, "Nv01Free: free complete\n"); 1359 } 1360 else 1361 { 1362 NV_PRINTF(LEVEL_WARNING, 1363 "Nv01Free: free failed; status: %s (0x%08x)\n", 1364 nvstatusToString(status), status); 1365 NV_PRINTF(LEVEL_WARNING, "Nv01Free: client:0x%x object:0x%x\n", 1366 hClient, hObject); 1367 } 1368 1369 return status; 1370 } 1371 1372 NV_STATUS 1373 rmapiFreeWithSecInfoTls 1374 ( 1375 RM_API *pRmApi, 1376 NvHandle hClient, 1377 NvHandle hObject, 1378 NvU32 flags, 1379 API_SECURITY_INFO *pSecInfo 1380 ) 1381 { 1382 THREAD_STATE_NODE threadState; 1383 NV_STATUS status; 1384 1385 threadStateInit(&threadState, THREAD_STATE_FLAGS_NONE); 1386 1387 status = rmapiFreeWithSecInfo(pRmApi, hClient, hObject, flags, pSecInfo); 1388 1389 threadStateFree(&threadState, THREAD_STATE_FLAGS_NONE); 1390 1391 return status; 1392 } 1393 1394 NV_STATUS 1395 rmapiFreeClientList 1396 ( 1397 RM_API *pRmApi, 1398 NvHandle *phClientList, 1399 NvU32 numClients 1400 ) 1401 { 1402 if (!pRmApi->bHasDefaultSecInfo) 1403 return NV_ERR_NOT_SUPPORTED; 1404 1405 return pRmApi->FreeClientListWithSecInfo(pRmApi, phClientList, numClients, &pRmApi->defaultSecInfo); 1406 } 1407 1408 NV_STATUS 1409 rmapiFreeClientListWithSecInfo 1410 ( 1411 RM_API *pRmApi, 1412 NvHandle *phClientList, 1413 NvU32 numClients, 1414 API_SECURITY_INFO *pSecInfo 1415 ) 1416 { 1417 NV_STATUS status; 1418 OBJSYS *pSys = SYS_GET_INSTANCE(); 1419 NvU32 lockState = 0; 1420 NvU32 i; 1421 1422 NV_PRINTF(LEVEL_INFO, "Nv01FreeClientList: numClients: %d\n", numClients); 1423 1424 if (!pRmApi->bRmSemaInternal && osAcquireRmSema(pSys->pSema) != NV_OK) 1425 return NV_ERR_INVALID_LOCK_STATE; 1426 1427 if (pRmApi->bApiLockInternal) 1428 lockState |= RM_LOCK_STATES_API_LOCK_ACQUIRED; 1429 1430 if (pRmApi->bGpuLockInternal) 1431 lockState |= RM_LOCK_STATES_ALLOW_RECURSIVE_LOCKS; 1432 1433 for (i = 0; i < numClients; ++i) 1434 rmapiControlCacheFreeClientEntry(phClientList[i]); 1435 1436 status = serverFreeClientList(&g_resServ, phClientList, numClients, lockState, pSecInfo); 1437 1438 if (!pRmApi->bRmSemaInternal) 1439 osReleaseRmSema(pSys->pSema, NULL); 1440 1441 if (status == NV_OK) 1442 { 1443 NV_PRINTF(LEVEL_INFO, "Nv01FreeClientList: free complete\n"); 1444 } 1445 else 1446 { 1447 NV_PRINTF(LEVEL_WARNING, 1448 "Nv01FreeList: free failed; status: %s (0x%08x)\n", 1449 nvstatusToString(status), status); 1450 } 1451 1452 return status; 1453 } 1454 1455 NV_STATUS 1456 rmapiFreeClientListWithSecInfoTls 1457 ( 1458 RM_API *pRmApi, 1459 NvHandle *phClientList, 1460 NvU32 numClients, 1461 API_SECURITY_INFO *pSecInfo 1462 ) 1463 { 1464 THREAD_STATE_NODE threadState; 1465 NV_STATUS status; 1466 1467 threadStateInit(&threadState, THREAD_STATE_FLAGS_NONE); 1468 1469 status = rmapiFreeClientListWithSecInfo(pRmApi, phClientList, numClients, pSecInfo); 1470 1471 threadStateFree(&threadState, THREAD_STATE_FLAGS_NONE); 1472 1473 return status; 1474 } 1475 1476 NvBool 1477 serverRwApiLockIsOwner 1478 ( 1479 RsServer *pServer 1480 ) 1481 { 1482 return rmapiLockIsOwner(); 1483 } 1484 1485 NV_STATUS 1486 serverAllocResourceLookupLockFlags 1487 ( 1488 RsServer *pServer, 1489 RS_LOCK_ENUM lock, 1490 RS_RES_ALLOC_PARAMS_INTERNAL *pParams, 1491 LOCK_ACCESS_TYPE *pAccess 1492 ) 1493 { 1494 NV_ASSERT_OR_RETURN(pAccess != NULL, NV_ERR_INVALID_ARGUMENT); 1495 1496 if (lock == RS_LOCK_TOP) 1497 { 1498 RS_RESOURCE_DESC *pResDesc; 1499 1500 if (!serverSupportsReadOnlyLock(&g_resServ, RS_LOCK_TOP, RS_API_ALLOC_RESOURCE)) 1501 { 1502 *pAccess = LOCK_ACCESS_WRITE; 1503 return NV_OK; 1504 } 1505 1506 pResDesc = RsResInfoByExternalClassId(pParams->externalClassId); 1507 1508 if (pResDesc == NULL) 1509 { 1510 return NV_ERR_INVALID_CLASS; 1511 } 1512 1513 if (pResDesc->flags & RS_FLAGS_ACQUIRE_RO_API_LOCK_ON_ALLOC) 1514 *pAccess = LOCK_ACCESS_READ; 1515 else 1516 *pAccess = LOCK_ACCESS_WRITE; 1517 1518 return NV_OK; 1519 } 1520 1521 if (lock == RS_LOCK_RESOURCE) 1522 { 1523 *pAccess = LOCK_ACCESS_WRITE; 1524 return NV_OK; 1525 } 1526 1527 return NV_ERR_NOT_SUPPORTED; 1528 } 1529 1530 NV_STATUS 1531 serverFreeResourceLookupLockFlags 1532 ( 1533 RsServer *pServer, 1534 RS_LOCK_ENUM lock, 1535 RS_RES_FREE_PARAMS_INTERNAL *pParams, 1536 LOCK_ACCESS_TYPE *pAccess 1537 ) 1538 { 1539 NV_ASSERT_OR_RETURN(pAccess != NULL, NV_ERR_INVALID_ARGUMENT); 1540 1541 *pAccess = (serverSupportsReadOnlyLock(pServer, lock, RS_API_FREE_RESOURCE)) 1542 ? LOCK_ACCESS_READ 1543 : LOCK_ACCESS_WRITE; 1544 return NV_OK; 1545 } 1546