1 /*
2  * SPDX-FileCopyrightText: Copyright (c) 2015-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 "g_rs_resource_nvoc.h"
25 
26 #ifndef _RS_RESOURCE_H_
27 #define _RS_RESOURCE_H_
28 
29 #include "nvport/nvport.h"
30 #include "resserv/resserv.h"
31 #include "nvoc/object.h"
32 #include "resserv/rs_access_map.h"
33 
34 #ifdef __cplusplus
35 extern "C" {
36 #endif
37 
38 class RsSession;
39 
40 /**
41  * @defgroup RsResource
42  * @addtogroup RsResource
43  * @{*/
44 
45 #define ALLOC_STATE_INTERNAL_CLIENT_HANDLE   NVBIT(5)
46 
47 /*
48  * Locking operations for lock-metering
49  */
50 #define RS_LOCK_TRACE_INVALID     1
51 #define RS_LOCK_TRACE_ACQUIRE     1
52 #define RS_LOCK_TRACE_RELEASE     2
53 #define RS_LOCK_TRACE_ALLOC       3
54 #define RS_LOCK_TRACE_FREE        4
55 #define RS_LOCK_TRACE_CTRL        5
56 #define RS_LOCK_TRACE_MAP         6
57 #define RS_LOCK_TRACE_UNMAP       7
58 
59 /**
60  * Context information for top-level, resource-level, and client-level locking
61  * operations
62  */
63 struct RS_LOCK_INFO
64 {
65     RsClient *pClient;              ///< Pointer to client that was locked (if any)
66     RsClient *pSecondClient;        ///< Pointer to second client, for dual-client locking
67     RsResourceRef *pContextRef;     ///< User-defined reference
68     RsSession *pSession;            ///< Session object to be locked, if any
69     NvU32 flags;                    ///< RS_LOCK_FLAGS_*
70     NvU32 state;                    ///< RS_LOCK_STATE_*
71     NvU32 gpuMask;
72     NvU8  traceOp;                  ///< RS_LOCK_TRACE_* operation for lock-metering
73     NvU32 traceClassId;             ///< Class of initial resource that was locked for lock metering
74 };
75 
76 struct RS_RES_ALLOC_PARAMS_INTERNAL
77 {
78     NvHandle hClient;       ///< [in] The handle of the resource's client
79     NvHandle hParent;       ///< [in] The handle of the resource's parent. This may be a client or another resource.
80     NvHandle hResource;     ///< [inout] Server will assign a handle if this is 0, or else try the value provided
81     NvU32 externalClassId;  ///< [in] External class ID of resource
82     NvHandle hDomain;       ///< UNUSED
83 
84     // Internal use only
85     RS_LOCK_INFO           *pLockInfo;        ///< [inout] Locking flags and state
86     RsClient               *pClient;          ///< [out] Cached client
87     RsResourceRef          *pResourceRef;     ///< [out] Cached resource reference
88     NvU32                   allocFlags;       ///< [in] Allocation flags
89     NvU32                   allocState;       ///< [inout] Allocation state
90     API_SECURITY_INFO      *pSecInfo;
91 
92     void                   *pAllocParams;     ///< [in] Copied-in allocation parameters
93     NvU32                   paramsSize;       ///< [in] Copied-in allocation parameters size
94 
95     // ... Dupe alloc
96     RsClient               *pSrcClient;       ///< The client that is sharing the resource
97     RsResourceRef          *pSrcRef;          ///< Reference to the resource that will be shared
98 
99     RS_ACCESS_MASK         *pRightsRequested; ///< [in] Access rights requested on the new resource
100     // Buffer for storing contents of user mask. Do not use directly, use pRightsRequested instead.
101     RS_ACCESS_MASK          rightsRequestedCopy;
102 
103     RS_ACCESS_MASK         *pRightsRequired;  ///< [in] Access rights required to alloc this object type
104 };
105 
106 struct RS_RES_DUP_PARAMS_INTERNAL
107 {
108     NvHandle            hClientSrc;            ///< [in] The handle of the source resource's client
109     NvHandle            hResourceSrc;          ///< [in] The handle of the source resource.
110     NvHandle            hClientDst;            ///< [in] The handle of the destination resource's client (may be different from source client)
111     NvHandle            hParentDst;            ///< [in] The handle of the destination resource's parent.
112     NvHandle            hResourceDst;          ///< [inout] The handle of the destination resource. Generated if 0.
113     void               *pShareParams;          ///< [in] Copied-in sharing parameters
114     NvU32               flags;                 ///< [in] Flags to denote special cases ( Bug: 2859347 to track removal)
115     // Internal use only
116     RsClient           *pSrcClient;
117     RsResourceRef      *pSrcRef;
118     API_SECURITY_INFO  *pSecInfo;              ///< [in] Security info
119     RS_LOCK_INFO       *pLockInfo;             ///< [inout] Locking flags and state
120 };
121 
122 struct RS_RES_SHARE_PARAMS_INTERNAL
123 {
124     NvHandle            hClient;            ///< [in] The handle of the owner's client
125     NvHandle            hResource;          ///< [in] The handle of the resource.
126     RS_SHARE_POLICY    *pSharePolicy;       ///< [in] The policy to share with
127 
128     // Internal use only
129     API_SECURITY_INFO  *pSecInfo;           ///< [in] Security info
130     RS_LOCK_INFO       *pLockInfo;          ///< [inout] Locking flags and state
131 };
132 
133 #define RS_IS_COPY_CTOR(pParams) ((pParams)->pSrcRef != NULL)
134 
135 struct RS_RES_FREE_PARAMS_INTERNAL
136 {
137     NvHandle           hClient;         ///< [in] The handle of the resource's client
138     NvHandle           hResource;       ///< [in] The handle of the resource
139     NvBool             bInvalidateOnly; ///< [in] Free the resource, but don't release its handle
140     NvHandle           hDomain;         ///< UNUSED
141 
142     // Internal use only
143     NvBool             bHiPriOnly;      ///< [in] Only free if this is a high priority resources
144     NvBool             bDisableOnly;    ///< [in] Disable the target instead of freeing it (only applies to clients)
145     RS_LOCK_INFO      *pLockInfo;       ///< [inout] Locking flags and state
146     NvU32              freeFlags;       ///< [in] Flags for the free operation
147     NvU32              freeState;       ///< [inout] Free state
148     RsResourceRef     *pResourceRef;    ///< [inout] Cached RsResourceRef
149     NV_STATUS          status;          ///< [out] Status of free operation
150     API_SECURITY_INFO *pSecInfo;        ///< [in] Security info
151 };
152 
153 struct NVOC_EXPORTED_METHOD_DEF;
154 class OBJGPU;
155 class OBJGPUGRP;
156 
157 //
158 // RS_RES_CONTROL_PARAMS
159 //
160 // This structure encapsulates data sent to the cmd-specific rmctrl
161 // handlers.  Along with the arguments supplied by the requesting
162 // client (hClient, hObject, cmd, pParams, paramSize).
163 //
164 struct RS_RES_CONTROL_PARAMS_INTERNAL
165 {
166     NvHandle                hClient;          // client-specified NV01_ROOT object handle
167     NvHandle                hObject;          // client-specified object handle
168     NvU32                   cmd;              // client-specified command #
169     NvU32                   flags;            // flags related to control call execution
170     void                   *pParams;          // client-specified params (in kernel space)
171     NvU32                   paramsSize;       // client-specified size of pParams in bytes
172 
173     NvHandle                hParent;          // handle of hObject parent
174     OBJGPU                 *pGpu;             // ptr to OBJGPU struct if applicable
175     OBJGPUGRP              *pGpuGrp;          // ptr to OBJGPUGRP struct if applicable
176     RsResourceRef          *pResourceRef;     // ptr to RsResourceRef if object is managed by
177                                               // Resource Server
178     API_SECURITY_INFO       secInfo;          // information on privilege level and pointer location (user/kernel)
179     RS_LOCK_INFO           *pLockInfo;        ///< [inout] Locking flags and state
180     RS_CONTROL_COOKIE      *pCookie;
181     NvBool                  bInternal;        // True if control call was not issued from an external client
182     NvBool                  bDeferredApi;     // Indicates ctrl is being dispatched via deferred API
183 
184     struct RS_RES_CONTROL_PARAMS_INTERNAL *pLegacyParams; // RS-TODO removeme
185 };
186 
187 struct RS_RES_DTOR_PARAMS
188 {
189     CALL_CONTEXT                 *pFreeContext;
190     RS_RES_FREE_PARAMS_INTERNAL  *pFreeParams;
191 };
192 
193 /**
194  * Base class for all resources. Mostly a pure virtual interface which
195  * should be overridden to implement resource specific behavior.
196  */
197 NVOC_PREFIX(res) class RsResource : Object
198 {
199 public:
200 // private:
201 
202     /**
203      * Back-reference to the RsResourceRef that owns this object
204      */
205     RsResourceRef *pResourceRef;
206 
207     /**
208      * Params for dtor
209      */
210     RS_RES_DTOR_PARAMS dtorParams;
211 
212     /**
213      * Flag that indicates whether the RsResource was constructed. If params to
214      * resConstruct are null the Resource ctor and dtor will be skipped. This is
215      * only added for migration where the entire class hierarchy can't be
216      * converted at once.
217      *
218      * RS-TODO: Remove once migrations are finished (added initially for
219      * DmaObject)
220      */
221     NvBool bConstructed;
222 
223 public:
224 
225     /**
226      * Resource initializer
227      * @param[in]   pResource Resource object to init
228      * @param[in]   pCallContext
229      * @param[in]   params Resource create parameters
230      */
231     NV_STATUS resConstruct(RsResource *pResource, CALL_CONTEXT *pCallContext, RS_RES_ALLOC_PARAMS_INTERNAL *pParams);
232 
233     /**
234      * Returns TRUE if the resource can be copied
235      */
236     virtual NvBool resCanCopy(RsResource *pResource);
237 
238     /**
239      * Returns TRUE if the resources are duplicates
240      */
241     virtual NV_STATUS resIsDuplicate(RsResource *pResource, NvHandle hMemory, NvBool *pDuplicate);
242 
243     /**
244      * Resource destructor
245      * @param[in]   pResource Resource object to destruct
246      */
247     void resDestruct(RsResource *pResource);
248 
249     /**
250      * Resource destructor prologue (occurs before mappings are torn-down)
251      * @param[in]   pResource Resource object to destruct
252      */
253     virtual void resPreDestruct(RsResource *pResource);
254 
255     /**
256      * Resource dtors take no parameters, so set them here.
257      * @param[in]   pResource
258      * @param[in]   pCallContext
259      * @param[in]   params Resource destroy parameters
260      */
261     NV_STATUS resSetFreeParams(RsResource *pResource, CALL_CONTEXT *pCallContext, RS_RES_FREE_PARAMS_INTERNAL *pParams);
262 
263     /**
264      * Resource dtors take no parameters, so get them here.
265      * @param[in]   pResource
266      * @param[out]  ppCallContext
267      * @param[out]  ppParams Resource destroy parameters
268      */
269     NV_STATUS resGetFreeParams(RsResource *pResource, CALL_CONTEXT **ppCallContext, RS_RES_FREE_PARAMS_INTERNAL **ppParams);
270 
271     /**
272      * Lookup a control call entry from a NVOC export table
273      *
274      * @param[in]       pResource
275      * @param[in]       pParams
276      * @param[out]      ppEntry
277      */
278     virtual NV_STATUS resControlLookup(RsResource *pResource,
279                                        RS_RES_CONTROL_PARAMS_INTERNAL *pParams,
280                                        const struct NVOC_EXPORTED_METHOD_DEF **ppEntry);
281 
282     /**
283      * Dispatch resource control call
284      * @param[in]   pResource
285      * @param[in]   pCallContext
286      * @param[in]   pParams
287      */
288     virtual NV_STATUS resControl(RsResource *pResource, CALL_CONTEXT *pCallContext,
289                                  RS_RES_CONTROL_PARAMS_INTERNAL *pParams);
290 
291     /**
292      * Early filter for control calls we don't want to service on a particular platform
293      *
294      * @param[in]   pResource
295      * @param[in]   pCallContext
296      * @param[in]   pParams
297      */
298     virtual NV_STATUS resControlFilter(RsResource *pResource, CALL_CONTEXT *pCallContext,
299                                        RS_RES_CONTROL_PARAMS_INTERNAL *pParams);
300 
301     /**
302      * Serialize the control parameters if they are going to GSP/Host, not serialized, and support serialization
303      * Or
304      * Deserialize the control parameters if necessary and replace the inner params pointer with the deserialized params
305      *
306      * @param[in]   pResource
307      * @param[in]   pCallContext
308      * @param[in]   pParams
309      */
310     virtual NV_STATUS resControlSerialization_Prologue(RsResource *pResource, CALL_CONTEXT *pCallContext,
311                                                        RS_RES_CONTROL_PARAMS_INTERNAL *pParams);
312 
313     /**
314      * Deserialize the parameters returned from GSP if client did not pass serialized params
315      * Or
316      * Serialize the control parameters if client expects it and restore the original inner params pointer
317      *
318      * @param[in]   pResource
319      * @param[in]   pCallContext
320      * @param[in]   pParams
321      */
322     virtual void resControlSerialization_Epilogue(RsResource *pResource, CALL_CONTEXT *pCallContext,
323                                                   RS_RES_CONTROL_PARAMS_INTERNAL *pParams);
324 
325     /**
326      * Operations performed right before the control call is executed. Default stubbed.
327      *
328      * @param[in]   pResource
329      * @param[in]   pCallContext
330      * @param[in]   pParams
331      */
332     virtual NV_STATUS resControl_Prologue(RsResource *pResource, CALL_CONTEXT *pCallContext,
333                                  RS_RES_CONTROL_PARAMS_INTERNAL *pParams);
334 
335     /**
336      * Operations performed right after the control call is executed. No return value. (void)
337      *
338      * @param[in]   pResource
339      * @param[in]   pCallContext
340      * @param[in]   pParams
341      */
342     virtual void resControl_Epilogue(RsResource *pResource, CALL_CONTEXT *pCallContext,
343                                  RS_RES_CONTROL_PARAMS_INTERNAL *pParams);
344 
345     /**
346      * Creates a mapping of the underlying resource in the physical address space of the requested process.
347      *
348      * The difference between serverResMap and resMap is that resMap provides a locked physical address
349      * and serverResMap creates a virtual mapping to the physical address. For virtualization, the
350      * tandem resource servers should be able to map a host physical address in a guest user space
351      * VA without any resource-specific VA mapping code.
352      *
353      * Not all resources support mapping.
354      *
355      * @param[in]       pResource Resource to map
356      * @param[in]       pCallContext
357      * @param[inout]    pCpuMapping
358      */
359     virtual NV_STATUS resMap(RsResource *pResource,
360                              CALL_CONTEXT *pCallContext,
361                              RS_CPU_MAP_PARAMS *pParams,
362                              RsCpuMapping *pCpuMapping);
363 
364     /**
365      * Release a virtual address mapping
366      * @param[in]   pResource Resource to map
367      * @param[in]   pCallContext
368      * @param[in]   pCpuMapping
369      */
370     virtual NV_STATUS resUnmap(RsResource *pResource, CALL_CONTEXT *pCallContext, RsCpuMapping *pCpuMapping);
371 
372      /**
373      * Maps to this resource from another resource
374      * Not all resources can be mapped to, in such a case returns NV_ERR_INVALID_OBJECT_HANDLE
375      *
376      * @param[in] pResource
377      * @param[inout] pParams
378      */
379     virtual NV_STATUS resMapTo(RsResource *pResource, RS_RES_MAP_TO_PARAMS *pParams);
380 
381     /**
382      * Unmaps a resource mapped to this resource
383      * Not all resources can be unmapped, in such a case returns NV_ERR_INVALID_OBJECT_HANDLE
384      *
385      * @param[in] pResource
386      * @param[in] pParams
387      */
388     virtual NV_STATUS resUnmapFrom(RsResource *pResource, RS_RES_UNMAP_FROM_PARAMS *pParams);
389 
390     /**
391      * Gets a refcount for any underlying shared resource
392      * @returns refcount
393      */
394     virtual NvU32 resGetRefCount(RsResource *pResource);
395 
396     /**
397      * Decides whether the invoking client should be granted an access right on this resource.
398      *
399      * The purpose of providing this function is to provide subclassed resources the ability
400      * to set custom policies for granting access rights. These policies can be implemented
401      * based on the ambient privilege of the caller, such as the PID.
402      *
403      * @param[in]  pResource The resource for which the access right will be granted
404      * @param[in]  pInvokingClient The client requesting the access right
405      * @param[in]  pAllocParams The alloc params struct passed into the alloc call,
406      *             NULL if called from outside the Alloc path
407      * @param[in]  accessRight The access right to be granted
408      * @returns NV_TRUE if the access right should be granted, and NV_FALSE otherwise
409      */
410     virtual NvBool resAccessCallback(RsResource *pResource, RsClient *pInvokingClient, void *pAllocParams, RsAccessRight accessRight);
411 
412     /**
413      * Decides whether rights can be shared with a client under a certain policy.
414      *
415      * The purpose of this function is to provide subclasses the ability to set custom definitions
416      * for how certain policies will share. Certain share types can then be created to work based
417      * on components not stored directly in resserv, such as PID.
418      *
419      * @param[in]    pResource The resource being shared
420      * @param[in]    pInvokingClient The client being shared with
421      * @param[in]    pParentRef dstParent if calling from DupObject, NULL otherwise
422      * @param[in]    pSharePolicy The policy under which to share
423      * @returns NV_TRUE if the share policy applies and rights should be shared, NV_FALSE otherwise
424      */
425     virtual NvBool resShareCallback(RsResource *pResource, RsClient *pInvokingClient, RsResourceRef *pParentRef, RS_SHARE_POLICY *pSharePolicy);
426 
427     /**
428      * Adds dependants that aren't in childRefMap or depRefMap to the pending free list.
429      *
430      * Due to RAM constraints, some classes can add more dependants that aren't
431      * represented in childRefMap or depRefMap. They can override this function
432      * to put them in the pending free list while we are updating it.
433      *
434      * @param[in]    pClient
435      * @param[in]    pResource      The RsResource with potential additional dependants
436      * @param[in]    pReference     The pReference to pass in to
437      *                              clientUpdatePendingFreeList()
438      */
439     virtual void resAddAdditionalDependants(RsClient *pClient, RsResource *pResource, RsResourceRef *pReference);
440 };
441 
442 /* @} */
443 
444 class OBJGPU;
445 
446 /**
447  * @defgroup RsCpuMapping
448  * @addtogroup RsCpuMapping
449  * @{*/
450 struct RsCpuMapping
451 {
452     NvU64 offset;
453     NvU64 length;
454     NvU32 flags;
455     NvP64 pLinearAddress;
456     RsResourceRef *pContextRef;      ///< Context resource that may be needed for the mapping
457     void *pContext;                  ///< Additional context data for the mapping
458     NvU32 processId;
459 
460     RS_CPU_MAPPING_PRIVATE *pPrivate; ///< Opaque struct allocated and freed by resserv on behalf of the user
461 };
462 MAKE_LIST(RsCpuMappingList, RsCpuMapping);
463 
464 /**
465  * CPU mapping parameters
466  */
467 struct RS_CPU_MAP_PARAMS
468 {
469     NvHandle                hClient;
470     NvHandle                hDevice;
471     NvHandle                hMemory;
472     NvU64                   offset;         ///< [in] Offset into the resource
473     NvU64                   length;         ///< [in] Size of the region to map
474     NvP64                  *ppCpuVirtAddr;
475     NvU32                   flags;          ///< [in] Resource-specific flags
476 
477     // Passed from RM into CpuMapping
478     NvU32                   protect;        ///< [in] Protection flags
479     NvBool                  bKernel;
480 
481     /// [in] hContext Handle of resource that provides a context for the mapping (e.g., subdevice for channel map)
482     NvHandle hContext;
483 
484     RS_LOCK_INFO   *pLockInfo;              ///< [inout] Locking flags and state
485     API_SECURITY_INFO *pSecInfo;            ///< [in] Security Info
486 };
487 
488 /**
489  * CPU unmapping params for resource server tests
490  */
491 struct RS_CPU_UNMAP_PARAMS
492 {
493     NvHandle                hClient;
494     NvHandle                hDevice;
495     NvHandle                hMemory;
496     NvP64                   pLinearAddress; ///< [in] Address of mapped memory
497     NvU32                   flags;          ///< [in] Resource-specific flags
498     NvU32                   processId;
499     NvBool                  bTeardown;      ///< [in] Unmap operation is due to client teardown
500 
501     /// [in] hContext Handle of resource that provides a context for the mapping (e.g., subdevice for channel map)
502     NvHandle                hContext;
503 
504     // RM-only
505     void                   *pProcessHandle;
506 
507     NvBool        (*fnFilter)(RsCpuMapping*);   ///< [in] Mapping-filter function
508     RS_LOCK_INFO   *pLockInfo;                  ///< [inout] Locking flags and state
509     API_SECURITY_INFO *pSecInfo;                ///< [in] Security Info
510 };
511 
512 /**
513  * CPU mapping back-reference
514  */
515 struct RS_CPU_MAPPING_BACK_REF
516 {
517     RsCpuMapping *pCpuMapping;  ///< Mapping linked to this backref
518     RsResourceRef *pBackRef;    ///< Resource reference with mapping
519 };
520 MAKE_LIST(RsCpuMappingBackRefList, RS_CPU_MAPPING_BACK_REF);
521 /* @} */
522 
523 /**
524  * @defgroup RsInterMapping
525  * @addtogroup RsInterMapping
526  * @{*/
527 struct RS_INTER_MAP_PARAMS
528 {
529     NvHandle        hClient;
530     NvHandle        hMapper;
531     NvHandle        hMappable;
532     NvHandle        hDevice;
533     NvU64           offset;
534     NvU64           length;
535     NvU32           flags;
536     NvU64           dmaOffset;              ///< [inout] RS-TODO rename this
537     void           *pMemDesc;               ///< [out]
538 
539     // Internal use only
540     RS_LOCK_INFO   *pLockInfo;              ///< [inout] Locking flags and state
541     API_SECURITY_INFO *pSecInfo;            ///< [in] Security Info
542 
543     RS_INTER_MAP_PRIVATE *pPrivate;         ///< Opaque struct controlled by caller
544 };
545 
546 struct RS_INTER_UNMAP_PARAMS
547 {
548     NvHandle        hClient;
549     NvHandle        hMapper;
550     NvHandle        hMappable;
551     NvHandle        hDevice;
552     NvU32           flags;
553     NvU64           dmaOffset;              ///< [in] RS-TODO rename this
554     void           *pMemDesc;               ///< MEMORY_DESCRIPTOR *
555 
556     // Internal use only
557     RS_LOCK_INFO   *pLockInfo;              ///< [inout] Locking flags and state
558     API_SECURITY_INFO *pSecInfo;            ///< [in] Security Info
559 
560     RS_INTER_UNMAP_PRIVATE *pPrivate;       ///< Opaque struct controlled by caller
561 };
562 
563 /**
564  * Inter-mapping information
565  * Used to keep track of inter-mappings and unmap them on free
566  */
567 struct RsInterMapping
568 {
569     // RsResourceRef *pMapperRef     ///< (Implied) the resource that created and owns this mapping (this resource)
570     RsResourceRef *pMappableRef;     ///< The resource being mapped by the mapper (e.g. hMemory)
571     RsResourceRef *pContextRef;      ///< A resource used to provide additional context for the mapping (e.g. hDevice)
572     NvU32 flags;                     ///< Flags passed when mapping, same flags also passed when unmapping
573     NvU64 dmaOffset;
574     void *pMemDesc;
575 };
576 MAKE_LIST(RsInterMappingList, RsInterMapping);
577 
578 /**
579  * Inter-mapping back-reference
580  */
581 struct RS_INTER_MAPPING_BACK_REF
582 {
583     RsResourceRef *pMapperRef;       ///< Resource reference with mapping
584     RsInterMapping *pMapping;        ///< Pointer to the inter-mapping linked to this backref
585 };
586 MAKE_LIST(RsInterMappingBackRefList, RS_INTER_MAPPING_BACK_REF);
587 /* @} */
588 
589 typedef struct RS_RESOURCE_DESC RS_RESOURCE_DESC;
590 RS_RESOURCE_DESC *RsResInfoByExternalClassId(NvU32);
591 NvU32 RsResInfoGetInternalClassId(const RS_RESOURCE_DESC *);
592 
593 /**
594  * A reference to a resource that has been allocated in RM.
595  */
596 struct RsResourceRef
597 {
598     RsClient   *pClient;            ///< Pointer to the client that owns the ref
599     RsResource *pResource;          ///< Pointer to the actual resource
600     NvHandle    hResource;          ///< Resource handle
601     struct RsResourceRef *pParentRef; ///< Parent resource reference
602     RsIndex     childRefMap;        ///< Child reference multi-map: { internalClassId -> { handle -> RsResourceRef } }
603 
604     /**
605      * Cached reference multi-map: { internalClassId -> { handle -> RsResourceRef } }
606      *
607      * The resource reference cache is a one-way association between this resource reference and
608      * any other resource reference. Resource server does not populate the cache so it is up to the
609      * resource implementation to manage it. clientRefIter can be used to iterate this cache.
610      */
611     RsIndex     cachedRefMap;
612 
613     /**
614      * Dependants reference multi-map: { internalClassId -> { handle -> RsResourceRef } }
615      *
616      * A map of all resources that strongly depend on this resource.
617      */
618     RsIndex     depRefMap;
619 
620     /**
621      * Dependants back-reference multi-map: { internalClassId -> { handle -> RsResourceRef } }
622      *
623      * AKA dependencies map
624      *
625      * A map of all resources that this resource strongly depends on.
626      */
627     RsIndex     depBackRefMap;
628 
629     /**
630      * Policy under which this resource can be shared with other clients
631      */
632     RsShareList     sharePolicyList;
633     NvBool          bSharePolicyListModified;
634 
635     /**
636      * A mask of the access rights that the owner client has on this object.
637      */
638     RS_ACCESS_MASK accessMask;
639 
640     const RS_RESOURCE_DESC *pResourceDesc; ///< Cached pointer to the resource descriptor
641     NvU32       internalClassId;    ///< Internal resource class id
642     NvU32       externalClassId;    ///< External resource class id
643     NvU32       depth;              ///< The depth of this reference in the resource graph
644     NvBool      bInvalidated;       ///< Reference has been freed but not removed yet
645 
646     RsCpuMappingList cpuMappings;   ///< List of CPU mappings to the resource from this resource reference
647     RsCpuMappingBackRefList backRefs;  ///< List of references that have this reference as a mapping context
648 
649     RsInterMappingList interMappings;        ///< List of inter-resource mappings created by this resource
650     RsInterMappingBackRefList interBackRefs; ///< List of inter-resource mappings this resource has been mapped into
651 
652     RsSession *pSession;          ///< If set, this ref depends on a shared session
653     RsSession *pDependantSession; ///< If set, this ref is depended on by a shared session
654 
655     ListNode   freeNode;        ///< Links to the client's pendingFreeList
656 };
657 MAKE_MAP(RsRefMap, RsResourceRef);
658 MAKE_INTRUSIVE_LIST(RsRefFreeList, RsResourceRef, freeNode);
659 
660 
661 // Iterator data structure to save state while walking through a list
662 struct RS_ITERATOR
663 {
664     union
665     {
666         RsRefMapIter      mapIt; ///< Map iterator for all resource references under a client
667         RsIndexIter idxIt; ///< Index iterator for child references of a resource reference
668     };
669 
670     RsClient *pClient;
671     RsResourceRef *pScopeRef;    ///< Reference to the resource that limits the scope of iteration
672     NvU32 internalClassId;
673     RsResourceRef *pResourceRef; ///< Resource ref that is being iterated over
674     NvU8 type;                   ///< RS_ITERATE_*
675     NvBool bExactMatch;          ///< If true, internalClassId must match exactly; if false, also match classes derived from the internalClassId
676 };
677 
678 // Iterator data structure to save state while walking through a resource tree in pre-order
679 struct RS_ORDERED_ITERATOR
680 {
681     NvS8 depth; ///< Depth of index stack; special value of -1 implies that the scope reference should be iterated over as well
682     RsIndexIter idxIt[RS_MAX_RESOURCE_DEPTH+1]; ///< Stack of index iterators for child references of a resource reference
683 
684     RsClient *pClient;
685     RsResourceRef *pScopeRef;    ///< Reference to the resource that limits the scope of iteration
686     NvU32 internalClassId;
687     NvBool bExactMatch;          ///< If true, internalClassId must match exactly; if false, also match classes derived from the internalClassId
688 
689     RsResourceRef *pResourceRef; ///< Resource ref that is being iterated over
690 };
691 
692 /**
693  * Macro for looking up a reference from a resource
694  */
695 #define RES_GET_REF(pResource) (staticCast((pResource), RsResource)->pResourceRef)
696 
697 /**
698  * Macro for looking up a resource handle from a resource
699  */
700 #define RES_GET_HANDLE(pResource) (RES_GET_REF(pResource)->hResource)
701 
702 /**
703  * Macro for looking up a resource's external class from a resource
704  */
705 #define RES_GET_EXT_CLASS_ID(pResource) (RES_GET_REF(pResource)->externalClassId)
706 
707 /**
708  * Macro for looking up a resource's parent handle from a resource
709  */
710 #define RES_GET_PARENT_HANDLE(pResource) (RES_GET_REF(pResource)->pParentRef->hResource)
711 
712 /**
713  * Macro for looking up a client from a resource
714  */
715 #define RES_GET_CLIENT(pResource) (RES_GET_REF(pResource)->pClient)
716 
717 /**
718  * Macro for looking up a client handle from a resource
719  */
720 #define RES_GET_CLIENT_HANDLE(pResource) (RES_GET_REF(pResource)->pClient->hClient)
721 
722 /**
723  * Find a CPU mapping owned by a resource reference
724  *
725  * @param[in]   pResourceRef
726  * @param[in]   pAddress The CPU virtual address of the mapping to search for
727  * @param[out]  ppMapping The returned mapping
728  */
729 NV_STATUS refFindCpuMapping(RsResourceRef *pResourceRef, NvP64 pAddress, RsCpuMapping **ppMapping);
730 
731 /**
732  * Find a CPU mapping owned by a resource reference
733  *
734  * @param[in]   pResourceRef
735  * @param[in]   pAddress The CPU virtual address of the mapping to search for
736  * @param[in]   fnFilter A user-provided filtering function that determines which mappings to ignore.
737  *                       If fnFilter is provided, then we will only return mappings for which fnFilter(mapping) returns NV_TRUE
738  *                       All mappings will be searched over if fnFilter is NULL.
739  * @param[out]  ppMapping The returned mapping
740  * @param[in]   fnFilter A user-provided filtering function that determines which mappings to ignore.
741  *                       If fnFilter is provided, then we will only return mappings for which fnFilter(mapping) returns NV_TRUE
742  *                       All mappings will be searched over if fnFilter is NULL.
743  */
744 NV_STATUS refFindCpuMappingWithFilter(RsResourceRef *pResourceRef, NvP64 pAddress, NvBool (*fnFilter)(RsCpuMapping*), RsCpuMapping **ppMapping);
745 
746 /**
747  * Find the first child object of given type
748  *
749  * @param[in]   pParentRef
750  * @param[in]   internalClassId
751  * @param[in]   bExactMatch If true, internalClassId must match exactly; if false, also match classes derived from the internalClassId
752  * @param[out]  pResourceRef The returned RsResourceRef (Optional)
753  */
754 NV_STATUS refFindChildOfType(RsResourceRef *pParentRef, NvU32 internalClassId, NvBool bExactMatch, RsResourceRef **ppResourceRef);
755 
756 /**
757  * Traverse up the reference parent-child hierarchy to find an ancestor reference of a given type
758  *
759  * @param[in]   pDescendantRef
760  * @param[in]   internalClassId
761  * @param[out]  ppAncestorRef The returned RsResourceRef (Optional)
762  */
763 NV_STATUS refFindAncestorOfType(RsResourceRef *pDescendantRef, NvU32 internalClassId, RsResourceRef **ppAncestorRef);
764 
765 /**
766  * Traverse up the reference parent-child hierarchy to find if a ref is a descendant of a given ancestor ref
767  *
768  * @param[in]  pDescendantRef The node to start searching from (not included in the search)
769  * @param[in]  pAncestorRef The node to search for in the parent-child hierarchy
770  */
771 NvBool refHasAncestor(RsResourceRef *pDescendantRef, RsResourceRef *pAncestorRef);
772 
773 /**
774  * Add a new mapping to a reference's mapping list
775  * @param[in] pResourceRef The reference to add a mapping to
776  * @param[in] pMapParams The parameters used to initialize the mapping
777  * @param[in] pContextRef A reference to a resource that provides a context for the mapping
778  * @param[out] ppMapping Pointer to the allocated mapping [optional]
779  */
780 NV_STATUS refAddMapping(RsResourceRef *pResourceRef, RS_CPU_MAP_PARAMS *pMapParams,
781                         RsResourceRef *pContextRef, RsCpuMapping **ppMapping);
782 
783 /**
784  * Remove an existing mapping from a reference's mapping list and remove back-references to the mapping.
785  * @param[in] pResourceRef The reference to add a mapping to
786  * @param[in] pMapping Pointer to the allocated mapping
787  */
788 void refRemoveMapping(RsResourceRef *pResourceRef, RsCpuMapping *pMapping);
789 
790 /**
791  * Allocate the user-controlled private pointer within the RsCpuMapping struct.
792  * Resserv will call this function to alloc the private struct when the mapping is created
793  * @param[in] pMapParams The parameters which were used to create the mapping
794  * @param[inout] pMapping Pointer to the mapping whose private struct should be allocated
795  */
796 NV_STATUS refAllocCpuMappingPrivate(RS_CPU_MAP_PARAMS *pMapParams, RsCpuMapping *pMapping);
797 
798 /**
799  * Free the user-controlled private pointer within the RsCpuMapping struct.
800  * Resserv will call this function to free the private struct when the mapping is removed
801  * @param[inout] pMapping Pointer to the mapping whose private struct should be freed
802  */
803 void refFreeCpuMappingPrivate(RsCpuMapping *pMapping);
804 
805 /**
806  * Add a dependency between this resource reference and a dependent reference.
807  * If this reference is freed, the dependent will be invalidated and torn down.
808  *
809  * @note Dependencies are implicit between a parent resource reference and child resource reference
810  * @note No circular dependency checking is performed
811  */
812 NV_STATUS refAddDependant(RsResourceRef *pResourceRef, RsResourceRef *pDependantRef);
813 
814 /**
815  * Remove the dependency between this resource reference and a dependent resource reference.
816  */
817 void refRemoveDependant(RsResourceRef *pResourceRef, RsResourceRef *pDependantRef);
818 
819 /**
820  * Find, Add, or Remove an inter-mapping between two resources to the Mapper's list of inter-mappings
821  * Inter-mappings are stored in the Mapper, and are matched by both the MappableRef and offset.
822  *
823  * @param[in] pMapperRef The reference which owns the inter-mapping
824  * @param[in] pMappableRef The reference which was mapped from to create the inter-mapping
825  *                         If NULL, will be ignored while matching inter-mappings
826  * @param[in] dmaOffset The offset value assigned while mapping, used to identify mappings
827  * @param[in] pContextRef A reference used during mapping and locking for additional context, used to identify mappings
828  * @param[inout] ppMapping Writes the resulting inter-mapping, if successfully created (Add) or found (Find)
829  * @param[in] pMapping The inter-mapping to remove (Remove)
830  */
831 NV_STATUS refFindInterMapping(RsResourceRef *pMapperRef, RsResourceRef *pMappableRef, RsResourceRef *pContextRef, NvU64 dmaOffset, RsInterMapping **ppMapping);
832 NV_STATUS refAddInterMapping(RsResourceRef *pMapperRef, RsResourceRef *pMappableRef, RsResourceRef *pContextRef, RsInterMapping **ppMapping);
833 void      refRemoveInterMapping(RsResourceRef *pMapperRef, RsInterMapping *pMapping);
834 
835 /**
836  * Store a resource reference in another reference's cache.
837  * @param[in]   pParentRef The resource reference that owns the cache
838  * @param[in]   pResourceRef The resource reference to store in the cache
839  */
840 NV_STATUS refCacheRef(RsResourceRef *pParentRef, RsResourceRef *pResourceRef);
841 
842 /**
843  * Remove a resource reference from another reference's cache
844  * @param[in]   pParentRef The resource reference that owns the cache
845  * @param[in]   pResourceRef The resource reference to de-index
846  */
847 NV_STATUS refUncacheRef(RsResourceRef *pParentRef, RsResourceRef *pResourceRef);
848 
849 /**
850  * Determine whether a reference is queued for removal
851  * @param[in]   pResourceRef
852  * @param[in]   pClient
853  */
854 NvBool    refPendingFree(RsResourceRef *pResourceRef, RsClient *pClient);
855 
856 
857 #ifdef __cplusplus
858 }
859 #endif
860 
861 #endif
862