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(&params, 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, &params);
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