1 /*
2  * SPDX-FileCopyrightText: Copyright (c) 2015-2021 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 "g_rs_server_nvoc.h"
25 
26 #ifndef _RS_SERVER_H_
27 #define _RS_SERVER_H_
28 
29 #include "nvport/nvport.h"
30 #include "resserv/resserv.h"
31 #include "resserv/rs_client.h"
32 #include "nvoc/runtime.h"
33 
34 #ifdef __cplusplus
35 extern "C" {
36 #endif
37 
38 /**
39  * @defgroup RsServer
40  * @addtogroup RsServer
41  * @{*/
42 
43 /**
44  * Book-keeping for individual client locks
45  */
46 struct CLIENT_ENTRY
47 {
48     PORT_RWLOCK    *pLock;
49     RsClient       *pClient;
50     NvHandle        hClient;
51     NvU64           lockOwnerTid; ///< Thread id of the lock owner
52 
53 #if LOCK_VAL_ENABLED
54     LOCK_VAL_LOCK   lockVal;
55 #endif
56 };
57 
58 /**
59  * Base-class for objects that are shared among multiple
60  * RsResources (including RsResources from other clients)
61  */
62 NVOC_PREFIX(shr) class RsShared : Object
63 {
64 public:
65     NV_STATUS shrConstruct(RsShared *pShared);
66     void      shrDestruct(RsShared *pShared);
67 
68     NvS32 refCount;
69     MapNode node;
70 };
71 MAKE_INTRUSIVE_MAP(RsSharedMap, RsShared, node);
72 
73 /**
74  * Utility class for objects that can reference
75  * multiple client handle spaces. Free's and control calls
76  * that occur on objects which reference an RsSession will
77  * need to acquire pLock first.
78  */
79 NVOC_PREFIX(session) class RsSession : RsShared
80 {
81 public:
82     NV_STATUS sessionConstruct(RsSession *pSession);
83     void sessionDestruct(RsSession *pSession);
84 
85     NV_STATUS sessionAddDependant(RsSession *pSession, RsResourceRef *pResourceRef);
86     NV_STATUS sessionAddDependency(RsSession *pSession, RsResourceRef *pResourceRef);
87     virtual void sessionRemoveDependant(RsSession *pSession, RsResourceRef *pResourceRef);
88     virtual void sessionRemoveDependency(RsSession *pSession, RsResourceRef *pResourceRef);
89 
90     PORT_RWLOCK *pLock;
91 #if LOCK_VAL_ENABLED
92     LOCK_VAL_LOCK lockVal;
93 #endif
94 
95     NvBool bValid;
96 
97     RsResourceRefList dependencies;
98     RsResourceRefList dependants;
99 // private:
100     NV_STATUS sessionCheckLocksForAdd(RsSession *pSession, RsResourceRef *pResourceRef);
101     void sessionCheckLocksForRemove(RsSession *pSession, RsResourceRef *pResourceRef);
102 };
103 
104 // Iterator data structure to save state while walking through a map
105 struct RS_SHARE_ITERATOR
106 {
107     RsSharedMapIter mapIt;
108     NvU32 internalClassId;
109     RsShared *pShared;          ///< Share that is being iterated over
110 };
111 
112 /**
113  * Top-level structure that RMAPI and RM interface with
114  *
115  * This class is all that needs to be allocated to use the resource server
116  * library.
117  *
118  * The RsServer interface should be kept as narrow as possible. Map and
119  * MapTo are added because <1> the unmap variants operate in addresses and not
120  * handles and <2> having explicit knowledge of map operations in the server is
121  * helpful when dealing with multiple levels of address spaces (e.g., guest
122  * user-mode, guest kernel-mode, host kernel-mode).
123  */
124 struct RsServer
125 {
126     /**
127      * Privilege level determines what objects a server is allowed to allocate, and
128      * also determines whether additional handle validation needs to be performed.
129      */
130     RS_PRIV_LEVEL             privilegeLevel;
131 
132     RsClientList             *pClientSortedList; ///< Bucket if linked List of clients (and their locks) owned by this server
133     NvU32                     clientCurrentHandleIndex;
134 
135     NvBool                    bConstructed; ///< Determines whether the server is ready to be used
136     PORT_MEM_ALLOCATOR       *pAllocator; ///< Allocator to use for all objects allocated by the server
137 
138     PORT_RWLOCK              *pClientListLock; ///< Lock that needs to be taken when accessing the client list
139 
140     PORT_SPINLOCK            *pShareMapLock; ///< Lock that needs to be taken when accessing the shared resource map
141     RsSharedMap               shareMap; ///< Map of shared resources
142 
143 #if (RS_STANDALONE)
144     NvU64                     topLockOwnerTid; ///< Thread id of top-lock owner
145     PORT_RWLOCK              *pTopLock; ///< Top-level resource server lock
146     PORT_RWLOCK              *pResLock; ///< Resource-level resource server lock
147 #if LOCK_VAL_ENABLED
148     LOCK_VAL_LOCK             topLockVal;
149     LOCK_VAL_LOCK             resLockVal;
150 #endif
151 #endif
152 
153     /// Print out a list of all resources that will be freed when a free request is made
154     NvBool                    bDebugFreeList;
155 
156     /// If true, control call param copies will be performed outside the top/api lock
157     NvBool                    bUnlockedParamCopy;
158 
159     // If true, calls annotated with ROUTE_TO_PHYISCAL will not grab global gpu locks
160     // (and the readonly API lock).
161     NvBool                    bRouteToPhysicalLockBypass;
162 
163     /**
164      * Setting this flag to false disables any attempts to
165      * automatically acquire access rights or to control access to resources by
166      * checking for access rights.
167      */
168     NvBool                    bRsAccessEnabled;
169 
170     /**
171      * Mask of interfaces (RS_API_*) that will use a read-only top lock by default
172      */
173     NvU32                     roTopLockApiMask;
174 
175     /// Share policies which clients default to when no other policies are used
176     RsShareList               defaultInheritedSharePolicyList;
177     /// Share policies to apply to all shares, regardless of other policies
178     RsShareList               globalInternalSharePolicyList;
179 
180     NvU32                     internalHandleBase;
181     NvU32                     clientHandleBase;
182 
183     NvU32                     activeClientCount;
184     NvU64                     activeResourceCount;
185 
186     /// List of clients that are de-activated and pending free
187     RsDisabledClientList      disabledClientList;
188     RsClient                 *pNextDisabledClient;
189     PORT_SPINLOCK            *pDisabledClientListLock;
190 };
191 
192 /**
193  * Construct a server instance. This must be performed before any other server
194  * operation.
195  *
196  * @param[in]   pServer This server instance
197  * @param[in]   privilegeLevel Privilege level for this resource server instance
198  * @param[in]   maxDomains Maximum number of domains to support, or 0 for the default
199  */
200 NV_STATUS serverConstruct(RsServer *pServer, RS_PRIV_LEVEL privilegeLevel, NvU32 maxDomains);
201 
202 /**
203  * Destroy a server instance. Destructing a server does not guarantee that child domains
204  * and clients will be appropriately freed. serverFreeDomain should be explicitly called
205  * on all allocated domains to ensure all clients and resources get cleaned up.
206  *
207  * @param[in]   pServer This server instance
208  */
209 NV_STATUS serverDestruct(RsServer *pServer);
210 
211 /**
212  * Allocate a domain handle. Domain handles are used to track clients created by a domain.
213  *
214  * @param[in]   pServer This server instance
215  * @param[in]   hParentDomain
216  * @param[in]   pAccessControl
217  * @param[out]  phDomain
218  *
219  */
220 NV_STATUS serverAllocDomain(RsServer *pServer, NvU32 hParentDomain, ACCESS_CONTROL *pAccessControl, NvHandle *phDomain);
221 
222 /**
223  * Verify that the calling user is allowed to perform the access. This check only
224  * applies to calls from RING_USER or RING_KERNEL. No check is performed in
225  * RING_HOST.
226  *
227  * @param[in]   pServer This server instance
228  * @param[in]   hDomain
229  * @param[in]   hClient
230  *
231  */
232 NV_STATUS serverValidate(RsServer *pServer, NvU32 hDomain, NvHandle hClient);
233 
234 /**
235  * Verify that the domain has sufficient permission to allocate the given class.
236  * @param[in] pServer
237  * @param[in] hDomain
238  * @param[in] externalClassId External resource class id
239  */
240 NV_STATUS serverValidateAlloc(RsServer *pServer, NvU32 hDomain, NvU32 externalClassId);
241 
242 /**
243  * Free a domain handle. All clients of this domain will be freed.
244  *
245  * @param[in]   pServer This server instance
246  * @param[in]   hDomain The handle of the domain to free
247  */
248 NV_STATUS serverFreeDomain(RsServer *pServer, NvHandle hDomain);
249 
250 /**
251  * Allocate a client handle. A client handle is required to allocate resources.
252  *
253  * @param[in]    pServer This server instance
254  * @param[inout] pParams Client allocation parameters
255  */
256 NV_STATUS serverAllocClient(RsServer *pServer, RS_RES_ALLOC_PARAMS_INTERNAL *pParams);
257 
258 /**
259  * Free a client handle. All resources references owned by the client will be
260  * freed.
261  *
262  * It is invalid to attempt to free a client from a user other than the one
263  * that allocated it.
264  *
265  * @param[in]   pServer This server instance
266  * @param[in]   pParams Client free params
267  */
268 NV_STATUS serverFreeClient(RsServer *pServer, RS_CLIENT_FREE_PARAMS* pParams);
269 
270 /**
271  * Mark a list of client handles as disabled. All CPU mappings owned by that
272  * client will be unmapped immediate, and the client will be marked as disabled.
273  * A call to @ref serverFreeDisabledClients will then free all such clients.
274  *
275  * It is invalid to attempt to free a client from a user other than the one
276  * that allocated it.
277  *
278  * @param[in]   pServer This server instance
279  * @param[in]   phClientList The list of client handles to disable
280  * @param[in]   numClients The number of clients in the list
281  * @param[in]   freeState User-defined free state
282  * @param[in]   pSecInfo Security Info
283  *
284  */
285 NV_STATUS serverMarkClientListDisabled(RsServer *pServer, NvHandle *phClientList, NvU32 numClients, NvU32 freeState, API_SECURITY_INFO *pSecInfo);
286 
287 /**
288  * Frees all currently disabled clients. All resources references owned by
289  * any of the clients will be freed.
290  * All priority resources will be freed first across all listed clients.
291  *
292  * NOTE: may return NV_WARN_MORE_PROCESSING_REQUIRED if not all clients were freed
293  *
294  * @param[in]   pServer   This server instance
295  * @param[in]   freeState User-defined free state
296  * @param[in]   limit     Max number of iterations to make returning; 0 means no limit
297  *
298  */
299 NV_STATUS serverFreeDisabledClients(RsServer *pServer, NvU32 freeState, NvU32 limit);
300 
301 /**
302  * Allocate a resource.
303  *
304  * It is invalid to attempt to allocate a client from a user other than the one
305  * that allocated it.
306  *
307  * @param[in]    pServer This server instance
308  * @param[inout] pParams The allocation parameters
309  */
310 NV_STATUS serverAllocResource(RsServer *pServer, RS_RES_ALLOC_PARAMS *params);
311 
312 /**
313  * Allocate a ref-counted resource share.
314  *
315  * @param[in] pServer
316  * @param[in] pClassInfo NVOC class info for the shared class (must derive from RsShared)
317  * @param[out] ppShare Allocated share
318  */
319 NV_STATUS serverAllocShare(RsServer *pServer, const NVOC_CLASS_INFO* pClassInfo, RsShared **ppShare);
320 
321 /**
322  * Allocate a ref-counted resource share with Halspec parent.
323  *
324  * @param[in] pServer
325  * @param[in] pClassInfo NVOC class info for the shared class (must derive from RsShared)
326  * @param[out] ppShare Allocated share
327  * @param[in] pHalspecParent Parent object whose Halspec can be used for the shared class object
328  */
329 NV_STATUS serverAllocShareWithHalspecParent(RsServer *pServer, const NVOC_CLASS_INFO* pClassInfo, RsShared **ppShare, Object *pHalspecParent);
330 
331 /**
332  * Get the ref-count of a resource share.
333  *
334  * @param[in] pServer
335  * @param[in] pShare Resource share
336  */
337 NvS32 serverGetShareRefCount(RsServer *pServer, RsShared *pShare);
338 
339 /**
340  * Increment the ref-count of a resource share.
341  *
342  * @param[in] pServer
343  * @param[in] pShare Resource share
344  */
345 NV_STATUS serverRefShare(RsServer *pServer, RsShared *pShare);
346 
347 /**
348  * Decrement the ref-count of a resource share. If the ref-count
349  * has reached zero, the resource share will be freed.
350  *
351  * @param[in] pServer
352  * @param[in] pShare Resource share
353  */
354 NV_STATUS serverFreeShare(RsServer *pServer, RsShared *pShare);
355 
356 /**
357  * Get an iterator to the elements in the server's shared object map
358  * @param[in] pServer
359  * @param[in] internalClassId If non-zero, only RsShared that are (or can be
360  *                            derived from) the specified class will be returned
361  */
362 RS_SHARE_ITERATOR serverShareIter(RsServer *pServer, NvU32 internalClassId);
363 
364 /**
365  * Get an iterator to the elements in the server's shared object map
366  */
367 NvBool serverShareIterNext(RS_SHARE_ITERATOR*);
368 
369 /**
370  * Set fixed client handle base in case clients wants to use a different
371  * base for client allocations
372  * @param[in] pServer
373  * @param[in] clientHandleBase
374  */
375 NV_STATUS serverSetClientHandleBase(RsServer *pServer, NvU32 clientHandleBase);
376 
377 /**
378  * Deserialize parameters for servicing command
379  *
380  * @param[in] pCallContext
381  * @param[in] cmd
382  * @param[in] pParams
383  * @param[in] paramsSize
384  * @param[in] flags
385  */
386 NV_STATUS serverDeserializeCtrlDown(CALL_CONTEXT *pCallContext, NvU32 cmd, void *pParams, NvU32 paramsSize, NvU32 *flags);
387 
388 /**
389  * Serialize parameters for servicing command
390  *
391  * @param[in] pCallContext
392  * @param[in] cmd
393  * @param[in] pParams
394  * @param[in] paramsSize
395  * @param[in] flags
396  */
397 NV_STATUS serverSerializeCtrlDown(CALL_CONTEXT *pCallContext, NvU32 cmd, void *pParams, NvU32 paramsSize, NvU32 *flags);
398 
399 /**
400  * Deserialize parameters for returning from command
401  *
402  * @param[in] pCallContext
403  * @param[in] cmd
404  * @param[in] pParams
405  * @param[in] paramsSize
406  * @param[in] flags
407  */
408 NV_STATUS serverDeserializeCtrlUp(CALL_CONTEXT *pCallContext, NvU32 cmd, void *pParams, NvU32 paramsSize, NvU32 *flags);
409 
410 /**
411  * Serialize parameters for returning from command
412  *
413  * @param[in] pCallContext
414  * @param[in] cmd
415  * @param[in] pParams
416  * @param[in] paramsSize
417  * @param[in] flags
418  */
419 NV_STATUS serverSerializeCtrlUp(CALL_CONTEXT *pCallContext, NvU32 cmd, void *pParams, NvU32 paramsSize, NvU32 *flags);
420 
421 /**
422  * Unset flag for reserializing control before going to GSP
423  * Used if kernel control servicing passes params to GSP without changing them
424  *
425  * @param[in] pCallContext
426  */
427 void serverDisableReserializeControl(CALL_CONTEXT *pCallContext);
428 
429 /**
430  * Free finn structures allocated for serializing/deserializing
431  *
432  * @param[in] pCallContext
433  * @param[in] pParams
434  */
435 void serverFreeSerializeStructures(CALL_CONTEXT *pCallContext, void *pParams);
436 
437 /**
438  * Return an available client handle for new client allocation
439  *
440  * @param[in] pServer This server instance
441  * @param[in] bInternalHandle Client is an RM internal client
442  * @param[in] pSecInfo Security context of this client allocation
443  */
444 extern NvU32 serverAllocClientHandleBase(RsServer *pServer, NvBool bInternalHandle, API_SECURITY_INFO *pSecInfo);
445 
446 /**
447  * Allocate a resource. Assumes top-level lock has been taken.
448  *
449  * It is invalid to attempt to allocate a client from a user other than the one
450  * that allocated it. User-implemented.
451  *
452  * @param[in]    pServer This server instance
453  * @param[inout] pParams The allocation parameters
454  */
455 extern NV_STATUS serverAllocResourceUnderLock(RsServer *pServer, RS_RES_ALLOC_PARAMS *pAllocParams);
456 
457 /**
458  * Call Free RPC for given resource. Assumes top-level lock has been taken.
459  *
460  * @param[in]    pServer This server instance
461  * @param[inout] pFreeParams The Free parameters
462  */
463 extern NV_STATUS serverFreeResourceRpcUnderLock(RsServer *pServer, RS_RES_FREE_PARAMS *pFreeParams);
464 
465 /**
466  * Copy-in parameters supplied by caller, and initialize API state. User-implemented.
467  * @param[in]   pServer
468  * @param[in]   pAllocParams    Resource allocation parameters
469  * @param[out]  ppApiState      User-defined API_STATE; should be allocated by this function
470  */
471 extern NV_STATUS serverAllocApiCopyIn(RsServer *pServer, RS_RES_ALLOC_PARAMS_INTERNAL *pAllocParams, API_STATE **ppApiState);
472 
473 /**
474  * Copy-out parameters supplied by caller, and release API state. User-implemented.
475  * @param[in]   pServer
476  * @param[in]   status      Status of allocation request
477  * @param[in]   pApiState   API_STATE for the allocation
478  */
479 extern NV_STATUS serverAllocApiCopyOut(RsServer *pServer, NV_STATUS status, API_STATE *pApiState);
480 
481 /**
482  * Obtain a second client handle to lock if required for the allocation.
483  * @param[in]   pParams  Resource allocation parameters
484  * @param[in]   phClient Client to lock, if any
485  */
486 extern NV_STATUS serverLookupSecondClient(RS_RES_ALLOC_PARAMS_INTERNAL *pParams, NvHandle *phClient);
487 
488 /**
489  * Acquires a top-level lock. User-implemented.
490  * @param[in]       pServer
491  * @param[in]       access          LOCK_ACCESS_READ or LOCK_ACCESS_WRITE
492  * @param[inout]    pLockInfo       Lock state
493  * @param[inout]    pReleaseFlags   Output flags indicating the locks that need to be released
494  */
495 extern NV_STATUS serverTopLock_Prologue(RsServer *pServer, LOCK_ACCESS_TYPE access, RS_LOCK_INFO *pLockInfo, NvU32 *pReleaseFlags);
496 
497 /**
498  * Releases a top-level lock. User-implemented.
499  * @param[in]       pServer
500  * @param[in]       access          LOCK_ACCESS_READ or LOCK_ACCESS_WRITE
501  * @param[inout]    pLockInfo       Lock state
502  * @param[inout]    pReleaseFlags   Flags indicating the locks that need to be released
503  */
504 extern void serverTopLock_Epilogue(RsServer *pServer, LOCK_ACCESS_TYPE access, RS_LOCK_INFO *pLockInfo, NvU32 *pReleaseFlags);
505 
506 /**
507  * Acquires a session lock.
508  * @param[in]       access          LOCK_ACCESS_READ or LOCK_ACCESS_WRITE
509  * @param[in]       pResourceRef    Resource reference to take session locks on
510  * @param[inout]    pLockInfo       Lock state
511  */
512 extern NV_STATUS serverSessionLock_Prologue(LOCK_ACCESS_TYPE access, RsResourceRef *pResourceRef, RS_LOCK_INFO *pLockInfo, NvU32 *pReleaseFlags);
513 
514 /**
515  * Releases a session lock.
516  * @param[in]       pServer
517  * @param[in]       access          LOCK_ACCESS_READ or LOCK_ACCESS_WRITE
518  * @param[inout]    pLockInfo       Lock state
519  * @param[inout]    pReleaseFlags   Flags indicating the locks that need to be released
520  */
521 extern void serverSessionLock_Epilogue(RsServer *pServer, LOCK_ACCESS_TYPE access, RS_LOCK_INFO *pLockInfo, NvU32 *pReleaseFlags);
522 
523 /**
524  * Acquires a resource-level lock. User-implemented.
525  * @param[in]       pServer
526  * @param[in]       access          LOCK_ACCESS_READ or LOCK_ACCESS_WRITE
527  * @param[inout]    pLockInfo       Lock state
528  * @param[inout]    pReleaseFlags   Output flags indicating the locks that need to be released
529  */
530 extern NV_STATUS serverResLock_Prologue(RsServer *pServer, LOCK_ACCESS_TYPE access, RS_LOCK_INFO *pLockInfo, NvU32 *pReleaseFlags);
531 
532 /**
533  * Releases a resource-level lock. User-implemented.
534  * @param[in]       pServer
535  * @param[in]       access          LOCK_ACCESS_READ or LOCK_ACCESS_WRITE
536  * @param[inout]    pLockInfo       Lock state
537  * @param[inout]    pReleaseFlags   Flags indicating the locks that need to be released
538  */
539 extern void serverResLock_Epilogue(RsServer *pServer, LOCK_ACCESS_TYPE access, RS_LOCK_INFO *pLockInfo, NvU32 *pReleaseFlags);
540 
541 /**
542  * WAR for additional tasks that must be performed after resource-level locks are released. User-implemented.
543  * @param[inout]    status       Allocation status
544  * @param[in]       bClientAlloc Caller is attempting to allocate a client
545  * @param[inout]    pParams      Allocation parameters
546  */
547 extern NV_STATUS serverAllocEpilogue_WAR(RsServer *pServer, NV_STATUS status, NvBool bClientAlloc, RS_RES_ALLOC_PARAMS_INTERNAL *pAllocParams);
548 
549 /**
550  * Free a resource reference and all of its descendants. This will decrease the
551  * resource's reference count. The resource itself will only be freed if there
552  * are no more references to it.
553  *
554  * It is invalid to attempt to free a resource from a user other than the one that allocated it.
555  *
556  * @param[in]   pServer This server instance
557  * @param[in]   pParams Free parameters
558  */
559 NV_STATUS   serverFreeResourceTree(RsServer *pServer, RS_RES_FREE_PARAMS *pParams);
560 
561 /**
562  * Same as serverFreeResourceTree except the top-level lock is assumed to have been taken.
563  *
564  * @param[in]   pServer This server instance
565  * @param[in]   pParams Free parameters
566  */
567 NV_STATUS   serverFreeResourceTreeUnderLock(RsServer *pServer, RS_RES_FREE_PARAMS *pParams);
568 
569 /**
570  * Updates the lock flags in the dup parameters
571  *
572  * @param[in]   pServer This server instance
573  * @param[in]   pParams Dup parameters
574  */
575 extern NV_STATUS   serverUpdateLockFlagsForCopy(RsServer *pServer, RS_RES_DUP_PARAMS *pParams);
576 
577 /**
578  * Updates the lock flags in the free parameters
579  *
580  * @param[in]   pServer This server instance
581  * @param[in]   pParams Free parameters
582  */
583 extern NV_STATUS   serverUpdateLockFlagsForFree(RsServer *pServer, RS_RES_FREE_PARAMS *pParams);
584 
585 /**
586  * Updates the lock flags for automatic inter-unmap during free
587  *
588  * @param[in]    pServer This server instance
589  * @param[inout] pParams Unmap params, contained pLockInfo will be modified
590  */
591 extern NV_STATUS serverUpdateLockFlagsForInterAutoUnmap(RsServer *pServer, RS_INTER_UNMAP_PARAMS *pParams);
592 
593 /**
594  * Initialize parameters for a recursive call to serverFreeResourceTree. User-implemented.
595  * @param[in]       hClient
596  * @param[in]       hResource
597  * @param[inout]    pParams
598  */
599 extern NV_STATUS   serverInitFreeParams_Recursive(NvHandle hClient, NvHandle hResource, RS_LOCK_INFO *pLockInfo, RS_RES_FREE_PARAMS *pParams);
600 
601 /**
602  * Common operations performed after top locks and client locks are taken, but before
603  * the control call is executed. This includes validating the control call cookie,
604  * looking up locking flags, parameter copy-in, and taking resource locks.
605  *
606  * @param[in]       pServer ResServ instance
607  * @param[in]       pParams Control call parameters
608  * @param[in]       pAccess Lock access type
609  * @param[inout]    pReleaseFlags Flags that indicate which locks were taken
610  */
611 NV_STATUS serverControl_Prologue(RsServer *pServer, RS_RES_CONTROL_PARAMS_INTERNAL *pParams, LOCK_ACCESS_TYPE *pAccess, NvU32 *pReleaseFlags);
612 
613 /**
614  * Common operations performed after the control call is executed. This
615  * includes releasing locks and parameter copy-out.
616  *
617  * @param[in]       pServer ResServ instance
618  * @param[in]       pParams Control call parameters
619  * @param[in]       pAccess Lock access type
620  * @param[inout]    pReleaseFlags Flags that indicate which locks were taken
621  * @param[in]       status Control call status
622  */
623 NV_STATUS serverControl_Epilogue(RsServer *pServer, RS_RES_CONTROL_PARAMS_INTERNAL *pParams, LOCK_ACCESS_TYPE access, NvU32 *pReleaseFlags, NV_STATUS status);
624 
625 /**
626  * Initialize a NVOC export control call cookie
627  *
628  * @param[in]       pExportedEntry
629  * @param[inout]    pCookie
630  */
631 extern void      serverControl_InitCookie(const struct NVOC_EXPORTED_METHOD_DEF *pExportedEntry, RS_CONTROL_COOKIE *pCookie);
632 
633 /**
634  * Validate a NVOC export control call cookie
635  *
636  * @param[in]       pParams
637  * @param[inout]    pCookie
638  */
639 extern NV_STATUS serverControl_ValidateCookie(RS_RES_CONTROL_PARAMS_INTERNAL *pParams, RS_CONTROL_COOKIE *pCookie);
640 
641 /**
642  * Copy-in control call parameters
643  *
644  * @param[in]       pServer ResServ instance
645  * @param[in]       pParams Control call parameters
646  * @param[inout]    pCookie Control call cookie
647  */
648 extern NV_STATUS serverControlApiCopyIn(RsServer *pServer,
649                                         RS_RES_CONTROL_PARAMS_INTERNAL *pParams,
650                                         RS_CONTROL_COOKIE *pCookie);
651 
652 /**
653  * Copy-out control call parameters
654  *
655  * @param[in]       pServer ResServ instance
656  * @param[in]       pParams Control call parameters
657  * @param[inout]    pCookie Control call cookie
658  */
659 extern NV_STATUS serverControlApiCopyOut(RsServer *pServer,
660                                          RS_RES_CONTROL_PARAMS_INTERNAL *pParams,
661                                          RS_CONTROL_COOKIE *pCookie,
662                                          NV_STATUS rmStatus);
663 
664 /**
665  * Determine whether an API supports a read-only lock for a given lock
666  * @param[in]       pServer ResServ instance
667  * @param[in]       lock    RS_LOCK_*
668  * @param[in]       api     RS_API*
669  */
670 NvBool serverSupportsReadOnlyLock(RsServer *pServer, RS_LOCK_ENUM lock, RS_API_ENUM api);
671 
672 /**
673  * Determine whether the current thread has taken the RW API lock
674  * @param[in]       pServer ResServ instance
675  */
676 extern NvBool serverRwApiLockIsOwner(RsServer *pServer);
677 
678 /**
679  * Lookup locking flags for a resource alloc
680  *
681  * @param[in]       pServer ResServ instance
682  * @param[in]       lock    RS_LOCK_*
683  * @param[in]       pParams Allocation parameters
684  * @param[out]      pAccess Computed lock access
685  */
686 extern NV_STATUS serverAllocResourceLookupLockFlags(RsServer *pServer,
687                                                     RS_LOCK_ENUM lock,
688                                                     RS_RES_ALLOC_PARAMS_INTERNAL *pParams,
689                                                     LOCK_ACCESS_TYPE *pAccess);
690 /**
691  *
692  * Lookup level locking flags for a resource free
693  *
694  * @param[in]       pServer ResServ instance
695  * @param[in]       lock    RS_LOCK_*
696  * @param[in]       pParams Allocation parameters
697  * @param[out]      pAccess Computed lock access
698  */
699 extern NV_STATUS serverFreeResourceLookupLockFlags(RsServer *pServer,
700                                                    RS_LOCK_ENUM lock,
701                                                    RS_RES_FREE_PARAMS_INTERNAL *pParams,
702                                                    LOCK_ACCESS_TYPE *pAccess);
703 
704 /**
705  * Lookup locking flags for a resource copy
706  *
707  * @param[in]       pServer ResServ instance
708  * @param[in]       lock    RS_LOCK_*
709  * @param[in]       pParams Allocation parameters
710  * @param[out]      pAccess Computed lock access
711  */
712 extern NV_STATUS serverCopyResourceLookupLockFlags(RsServer *pServer,
713                                                    RS_LOCK_ENUM lock,
714                                                    RS_RES_DUP_PARAMS *pParams,
715                                                    LOCK_ACCESS_TYPE *pAccess);
716 
717 /**
718  * Lookup locking flags for a resource access share
719  *
720  * @param[in]       pServer ResServ instance
721  * @param[in]       lock    RS_LOCK_*
722  * @param[in]       pParams Share parameters
723  * @param[out]      pAccess Computed lock access
724  */
725 extern NV_STATUS serverShareResourceLookupLockFlags(RsServer *pServer,
726                                                     RS_LOCK_ENUM lock,
727                                                     RS_RES_SHARE_PARAMS *pParams,
728                                                     LOCK_ACCESS_TYPE *pAccess);
729 
730 /**
731  * Lookup locking flags for a control call
732  *
733  * @param[in]       pServer ResServ instance
734  * @param[in]       lock    RS_LOCK_*
735  * @param[in]       pParams Control call parameters
736  * @param[in]       pCookie Control call cookie
737  * @param[out]      pAccess Computed lock access
738  */
739 extern NV_STATUS serverControlLookupLockFlags(RsServer *pServer,
740                                               RS_LOCK_ENUM lock,
741                                               RS_RES_CONTROL_PARAMS_INTERNAL *pParams,
742                                               RS_CONTROL_COOKIE *pCookie,
743                                               LOCK_ACCESS_TYPE *pAccess);
744 
745 /**
746  *
747  * Lookup locking flags for a map call
748  *
749  * @param[in]       pServer ResServ instance
750  * @param[in]       lock    RS_LOCK_*
751  * @param[in]       pParams CPU map parameters
752  * @param[out]      pAccess Computed lock access
753  */
754 extern NV_STATUS serverMapLookupLockFlags(RsServer *pServer,
755                                           RS_LOCK_ENUM lock,
756                                           RS_CPU_MAP_PARAMS *pParams,
757                                           LOCK_ACCESS_TYPE *pAccess);
758 
759 /**
760  * Lookup locking flags for an unmap call
761  *
762  * @param[in]       pServer ResServ instance
763  * @param[in]       lock    RS_LOCK_*
764  * @param[in]       pParams CPU unmap parameters
765  * @param[out]      pAccess Computed lock access
766  */
767 extern NV_STATUS serverUnmapLookupLockFlags(RsServer *pServer,
768                                             RS_LOCK_ENUM lock,
769                                             RS_CPU_UNMAP_PARAMS *pParams,
770                                             LOCK_ACCESS_TYPE *pAccess);
771 
772 /**
773  *
774  * Lookup locking flags for an inter-resource map call
775  *
776  * @param[in]       pServer ResServ instance
777  * @param[in]       lock    RS_LOCK_*
778  * @param[in]       pParams Inter-resource map parameters
779  * @param[out]      pAccess Computed lock access
780  */
781 extern NV_STATUS serverInterMapLookupLockFlags(RsServer *pServer,
782                                                RS_LOCK_ENUM lock,
783                                                RS_INTER_MAP_PARAMS *pParams,
784                                                LOCK_ACCESS_TYPE *pAccess);
785 
786 /**
787  *
788  * Lookup locking flags for an inter-resource unmap call
789  *
790  * @param[in]       pServer ResServ instance
791  * @param[in]       lock    RS_LOCK_*
792  * @param[in]       pParams Inter-resource unmap parameters
793  * @param[out]      pAccess Computed lock access
794  */
795 extern NV_STATUS serverInterUnmapLookupLockFlags(RsServer *pServer,
796                                                  RS_LOCK_ENUM lock,
797                                                  RS_INTER_UNMAP_PARAMS *pParams,
798                                                  LOCK_ACCESS_TYPE *pAccess);
799 
800 /**
801  * Fill the server's share policy lists with any default or global policies needed
802  */
803 extern NV_STATUS serverInitGlobalSharePolicies(RsServer *pServer);
804 
805 /**
806  * Issue a control command to a resource
807  *
808  * @param[in]   pServer This server instance
809  * @param[in]   pParams Control parameters
810  */
811 NV_STATUS serverControl(RsServer *pServer, RS_RES_CONTROL_PARAMS *pParams);
812 
813 /**
814  * Copy a resource owned by one client into another client.
815  *
816  * The clients must be in the same client handle space. The underlying
817  * resource is not duplicated, but it is refcounted so the resource will
818  * not be freed until the reference count hits zero.
819  *
820  * Copying a resource will fail if the user making the call does not own
821  * the source client.
822  *
823  * @param[in]    pServer This server instance
824  * @param[inout] pParams Resource sharing parameters
825  */
826 NV_STATUS serverCopyResource(RsServer *pServer, RS_RES_DUP_PARAMS *pParams);
827 
828 /**
829  * Share certain access rights to a resource with other clients using the provided share policy
830  *
831  * The policy entry passed in will be added to the object's share policy list.
832  * If the bRevoke is true, the policy will be removed instead.
833  *
834  * Sharing will fail if the user making the call does not own the source client.
835  *
836  * @param[in]    pServer This server instance
837  * @param[in] pParams Resource sharing parameters
838  */
839 NV_STATUS serverShareResourceAccess(RsServer *pServer, RS_RES_SHARE_PARAMS *pParams);
840 
841 /**
842  * Creates a CPU mapping of the resource in the virtual address space of the process.
843  *
844  * Not all resources support mapping.
845  *
846  * @param[in]   pServer This server instance
847  * @param[in]   hClient Client handle of the resource to map
848  * @param[in]   hResource Handle of the resource to map
849  * @param[inout] pParams CPU mapping parameters
850  */
851 NV_STATUS serverMap(RsServer *pServer, NvHandle hClient, NvHandle hResource, RS_CPU_MAP_PARAMS *pParams);
852 
853 /**
854  * Release a CPU virtual address unmapping
855  *
856  * @param[in]   pServer This server instance
857  * @param[in]   hClient Client handle of the resource to map
858  * @param[in]   hResource Handle of the resource to map
859  * @param[in]   pParams CPU unmapping parameters
860  */
861 NV_STATUS serverUnmap(RsServer *pServer, NvHandle hClient, NvHandle hResource, RS_CPU_UNMAP_PARAMS *pParams);
862 
863 /**
864  * Pre-map operations. Called with top/client locks acquired
865  * but not resource locks.
866  *
867  * @param[in] pServer
868  * @param[inout] pParams CPU mapping parameters
869  */
870 NV_STATUS serverMap_Prologue(RsServer *pServer, RS_CPU_MAP_PARAMS *pMapParams);
871 
872 /**
873  * Post-map operations. Called with top/client locks acquired
874  * but not resource locks.
875  *
876  * @param[in] pServer
877  * @param[inout] pParams CPU mapping parameters
878  */
879 void serverMap_Epilogue(RsServer *pServer, RS_CPU_MAP_PARAMS *pMapParams);
880 
881 /**
882  * Pre-unmap operations. Called with top/client locks acquired
883  * but not resource locks.
884  *
885  * @param[in] pServer
886  * @param[inout] pParams CPU mapping parameters
887  */
888 NV_STATUS serverUnmap_Prologue(RsServer *pServer, RS_CPU_UNMAP_PARAMS *pUnmapParams);
889 
890 /**
891  * Post-unmap operations. Called with top/client locks acquired
892  * but not resource locks.
893  *
894  * @param[in] pServer
895  * @param[inout] pParams CPU mapping parameters
896  */
897 void serverUnmap_Epilogue(RsServer *pServer, RS_CPU_UNMAP_PARAMS *pUnmapParams);
898 
899 /**
900  * Creates an inter-mapping between two resources
901  *
902  * Not all resources support mapping.
903  *
904  * @param[in]   pServer This server instance
905  * @param[inout] pParams mapping parameters
906  */
907 NV_STATUS serverInterMap(RsServer *pServer, RS_INTER_MAP_PARAMS *pParams);
908 
909 /**
910  * Release an inter-mapping between two resources
911  *
912  * @param[in]   pServer This server instance
913  * @param[in]   pParams unmapping parameters
914  */
915 NV_STATUS serverInterUnmap(RsServer *pServer, RS_INTER_UNMAP_PARAMS *pParams);
916 
917 /**
918  * Pre-inter-map operations. Called with top/client locks acquired.
919  * This function acquires resource locks.
920  *
921  * @param[in] pServer
922  * @param[in]  pMapperRef The resource that can be used to create the mapping
923  * @param[in]  pMappableRef The resource that can be mapped
924  * @param[inout] pMapParams mapping parameters
925  * @param[inout] pReleaseFlags Flags that indicate which locks were taken
926  */
927 NV_STATUS serverInterMap_Prologue(RsServer *pServer, RsResourceRef *pMapperRef, RsResourceRef *pMappableRef, RS_INTER_MAP_PARAMS *pMapParams, NvU32 *pReleaseFlags);
928 
929 /**
930  * Post-inter-map operations. Called with top, client, and resource locks acquired.
931  * This function releases resource locks.
932  *
933  * @param[in] pServer
934  * @param[inout] pMapParams mapping parameters
935  * @param[inout] pReleaseFlags Flags that indicate which locks were taken
936  */
937 void serverInterMap_Epilogue(RsServer *pServer, RS_INTER_MAP_PARAMS *pMapParams, NvU32 *pReleaseFlags);
938 
939 /**
940  * Pre-inter-unmap operations. Called with top, client, and resource locks acquired.
941  *
942  * @param[in] pServer
943  * @param[inout] pParams mapping parameters
944  */
945 NV_STATUS serverInterUnmap_Prologue(RsServer *pServer, RS_INTER_UNMAP_PARAMS *pUnmapParams);
946 
947 /**
948  * Post-inter-unmap operations. Called with top, client, and resource locks acquired.
949  *
950  * @param[in] pServer
951  * @param[inout] pParams mapping parameters
952  */
953 void serverInterUnmap_Epilogue(RsServer *pServer, RS_INTER_UNMAP_PARAMS *pUnmapParams);
954 
955 /**
956  * Acquire a client pointer from a client handle. The caller is responsible for
957  * ensuring that lock ordering is not violated (otherwise there can be
958  * deadlock): clients must be locked in increasing order of client index (not
959  * handle).
960  *
961  * @param[in]   pServer This server instance
962  * @param[in]   hClient The client to acquire
963  * @param[in]   lockAccess LOCK_ACCESS_READ or LOCK_ACCESS_WRITE
964  * @param[out]  ppClient Pointer to the RsClient
965  */
966 NV_STATUS serverAcquireClient(RsServer *pServer, NvHandle hClient, LOCK_ACCESS_TYPE lockAccess, RsClient **ppClient);
967 
968 /**
969  * Release a client pointer
970  *
971  * @param[in]  pServer This server instance
972  * @param[in]  lockAccess LOCK_ACCESS_READ or LOCK_ACCESS_WRITE
973  * @param[in]  pClient Pointer to the RsClient
974  */
975 NV_STATUS serverReleaseClient(RsServer *pServer, LOCK_ACCESS_TYPE lockAccess, RsClient *pClient);
976 
977 /**
978  * Get a client pointer from a client handle without taking any locks.
979  *
980  * @param[in]   pServer This server instance
981  * @param[in]   hClient The client to acquire
982  * @param[out]  ppClient Pointer to the RsClient
983  */
984 NV_STATUS serverGetClientUnderLock(RsServer *pServer, NvHandle hClient, RsClient **ppClient);
985 
986 /**
987  * Get the count of clients allocated under this resource server
988  *
989  * @param[in]   pServer This server instance
990  */
991 NvU32 serverGetClientCount(RsServer *pServer);
992 
993 /**
994  * Get the count of resources allocated under this resource server
995  *
996  * @param[in]   pServer This server instance
997  */
998 NvU64 serverGetResourceCount(RsServer *pServer);
999 
1000 /**
1001  * Swap a TLS call context entry and increment the TLS entry refcount.
1002  * A new TLS entry for call context will be allocated if necessary.
1003  *
1004  * @note This should be paired with a corresponding resservRestoreTlsCallContext call
1005  */
1006 NV_STATUS resservSwapTlsCallContext(CALL_CONTEXT **ppOldCallContext, CALL_CONTEXT *pNewCallContext);
1007 
1008 /**
1009  * Get the current TLS call context. This will not increment a refcount on the TLS entry.
1010  */
1011 CALL_CONTEXT *resservGetTlsCallContext(void);
1012 
1013 /**
1014  * Set a TLS call context entry and decrement the TLS entry refcount.
1015  * @note This should be paired with a corresponding resservSwapTlsCallContext call
1016  */
1017 NV_STATUS resservRestoreTlsCallContext(CALL_CONTEXT *pOldCallContext);
1018 
1019 /**
1020  * Find a resource reference of a given type from the TLS call context
1021  * @param[in]   internalClassId  Only return a reference if it matches this type
1022  * @param[in]   bSearchAncestors Search parents of the call context resource ref
1023  */
1024 RsResourceRef *resservGetContextRefByType(NvU32 internalClassId, NvBool bSearchAncestors);
1025 
1026 #ifdef __cplusplus
1027 }
1028 #endif
1029 
1030 #endif
1031