mirror of
https://github.com/NVIDIA/open-gpu-kernel-modules.git
synced 2026-03-03 04:09:50 +00:00
373 lines
15 KiB
C++
373 lines
15 KiB
C++
/*
|
|
* SPDX-FileCopyrightText: Copyright (c) 2015-2021 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
|
* SPDX-License-Identifier: MIT
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
* copy of this software and associated documentation files (the "Software"),
|
|
* to deal in the Software without restriction, including without limitation
|
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
* and/or sell copies of the Software, and to permit persons to whom the
|
|
* Software is furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in
|
|
* all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
* DEALINGS IN THE SOFTWARE.
|
|
*/
|
|
|
|
#include "g_resserv_nvoc.h"
|
|
|
|
#ifndef _RESSERV_H_
|
|
#define _RESSERV_H_
|
|
|
|
#include "nvoc/object.h"
|
|
|
|
#include "containers/list.h"
|
|
#include "containers/map.h"
|
|
#include "containers/multimap.h"
|
|
|
|
#include "nvtypes.h"
|
|
#include "nvstatus.h"
|
|
#include "nvos.h"
|
|
#include "nvsecurityinfo.h"
|
|
#include "rs_access.h"
|
|
|
|
#if LOCK_VAL_ENABLED
|
|
#include "lockval/lockval.h"
|
|
#endif
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
#if (RS_STANDALONE)
|
|
#include <stddef.h>
|
|
|
|
#ifndef NV_PRINTF
|
|
extern int g_debugLevel;
|
|
#define NV_PRINTF(level, format, ...) if (g_debugLevel) { printf(format, ##__VA_ARGS__); }
|
|
#endif
|
|
#include "utils/nvprintf.h"
|
|
#endif
|
|
|
|
//
|
|
// Forward declarations
|
|
//
|
|
typedef struct RsServer RsServer;
|
|
typedef struct RsDomain RsDomain;
|
|
typedef struct CLIENT_ENTRY CLIENT_ENTRY;
|
|
typedef struct RsResourceDep RsResourceDep;
|
|
typedef struct RsResourceRef RsResourceRef;
|
|
typedef struct RsInterMapping RsInterMapping;
|
|
typedef struct RsCpuMapping RsCpuMapping;
|
|
|
|
// RS-TODO INTERNAL and EXTERNAL params should be different structures
|
|
typedef struct RS_CLIENT_FREE_PARAMS_INTERNAL RS_CLIENT_FREE_PARAMS_INTERNAL;
|
|
typedef struct RS_CLIENT_FREE_PARAMS_INTERNAL RS_CLIENT_FREE_PARAMS;
|
|
typedef struct RS_RES_ALLOC_PARAMS_INTERNAL RS_RES_ALLOC_PARAMS_INTERNAL;
|
|
typedef struct RS_RES_ALLOC_PARAMS_INTERNAL RS_RES_ALLOC_PARAMS;
|
|
typedef struct RS_RES_DUP_PARAMS_INTERNAL RS_RES_DUP_PARAMS_INTERNAL;
|
|
typedef struct RS_RES_DUP_PARAMS_INTERNAL RS_RES_DUP_PARAMS;
|
|
typedef struct RS_RES_SHARE_PARAMS_INTERNAL RS_RES_SHARE_PARAMS_INTERNAL;
|
|
typedef struct RS_RES_SHARE_PARAMS_INTERNAL RS_RES_SHARE_PARAMS;
|
|
typedef struct RS_RES_ALLOC_PARAMS_INTERNAL RS_CLIENT_ALLOC_PARAMS_INTERNAL;
|
|
typedef struct RS_RES_ALLOC_PARAMS_INTERNAL RS_CLIENT_ALLOC_PARAMS;
|
|
typedef struct RS_RES_FREE_PARAMS_INTERNAL RS_RES_FREE_PARAMS_INTERNAL;
|
|
typedef struct RS_RES_FREE_PARAMS_INTERNAL RS_RES_FREE_PARAMS;
|
|
typedef struct RS_RES_CONTROL_PARAMS_INTERNAL RS_RES_CONTROL_PARAMS_INTERNAL;
|
|
typedef struct RS_RES_CONTROL_PARAMS_INTERNAL RS_RES_CONTROL_PARAMS;
|
|
typedef struct RS_RES_CONTROL_PARAMS_INTERNAL RS_LEGACY_CONTROL_PARAMS;
|
|
typedef struct RS_LEGACY_ALLOC_PARAMS RS_LEGACY_ALLOC_PARAMS;
|
|
typedef struct RS_LEGACY_FREE_PARAMS RS_LEGACY_FREE_PARAMS;
|
|
|
|
typedef struct RS_CPU_MAP_PARAMS RS_CPU_MAP_PARAMS;
|
|
typedef struct RS_CPU_UNMAP_PARAMS RS_CPU_UNMAP_PARAMS;
|
|
typedef struct RS_INTER_MAP_PARAMS RS_INTER_MAP_PARAMS;
|
|
typedef struct RS_INTER_UNMAP_PARAMS RS_INTER_UNMAP_PARAMS;
|
|
|
|
// Forward declarations for structs defined by user
|
|
typedef struct RS_RES_MAP_TO_PARAMS RS_RES_MAP_TO_PARAMS;
|
|
typedef struct RS_RES_UNMAP_FROM_PARAMS RS_RES_UNMAP_FROM_PARAMS;
|
|
typedef struct RS_INTER_MAP_PRIVATE RS_INTER_MAP_PRIVATE;
|
|
typedef struct RS_INTER_UNMAP_PRIVATE RS_INTER_UNMAP_PRIVATE;
|
|
typedef struct RS_CPU_MAPPING_PRIVATE RS_CPU_MAPPING_PRIVATE;
|
|
|
|
typedef struct RS_CPU_MAPPING_BACK_REF RS_CPU_MAPPING_BACK_REF;
|
|
typedef struct RS_INTER_MAPPING_BACK_REF RS_INTER_MAPPING_BACK_REF;
|
|
typedef struct RS_FREE_STACK RS_FREE_STACK;
|
|
typedef struct CALL_CONTEXT CALL_CONTEXT;
|
|
typedef struct ACCESS_CONTROL ACCESS_CONTROL;
|
|
typedef struct RS_ITERATOR RS_ITERATOR;
|
|
typedef struct RS_ORDERED_ITERATOR RS_ORDERED_ITERATOR;
|
|
typedef struct RS_SHARE_ITERATOR RS_SHARE_ITERATOR;
|
|
typedef struct API_STATE API_STATE;
|
|
typedef struct RS_LOCK_INFO RS_LOCK_INFO;
|
|
typedef struct RS_CONTROL_COOKIE RS_CONTROL_COOKIE;
|
|
typedef NV_STATUS RsCtrlFunc(struct RS_RES_CONTROL_PARAMS_INTERNAL*);
|
|
|
|
class RsClient;
|
|
class RsResource;
|
|
class RsShared;
|
|
|
|
MAKE_LIST(RsResourceRefList, RsResourceRef*);
|
|
MAKE_LIST(RsResourceList, RsResource*);
|
|
MAKE_LIST(RsHandleList, NvHandle);
|
|
MAKE_LIST(RsClientList, CLIENT_ENTRY*);
|
|
MAKE_LIST(RsShareList, RS_SHARE_POLICY);
|
|
MAKE_MULTIMAP(RsIndex, RsResourceRef*);
|
|
|
|
typedef NV_STATUS (*CtrlImpl_t)(RsClient*, RsResource*, void*);
|
|
|
|
typedef void *PUID_TOKEN;
|
|
|
|
//
|
|
// Defines
|
|
//
|
|
|
|
/// Domain handles must start at this base value
|
|
#define RS_DOMAIN_HANDLE_BASE 0xD0D00000
|
|
|
|
/// Client handles must start at this base value
|
|
#define RS_CLIENT_HANDLE_BASE 0xC1D00000
|
|
|
|
/// Internal Client handles start at this base value
|
|
#define RS_CLIENT_INTERNAL_HANDLE_BASE 0xC1E00000
|
|
|
|
/// VF Client handles start at this base value
|
|
#define RS_CLIENT_VF_HANDLE_BASE 0xE0000000
|
|
|
|
/// Get the VF client handle range for gfid
|
|
#define RS_CLIENT_GET_VF_HANDLE_BASE(gfid) (RS_CLIENT_VF_HANDLE_BASE + ((gfid) - 1) * RS_CLIENT_HANDLE_MAX)
|
|
|
|
//
|
|
// Print a warning if any client's resource count exceeds this
|
|
// threshold. Unless this was intentional, this is likely a client bug.
|
|
//
|
|
#define RS_CLIENT_RESOURCE_WARNING_THRESHOLD 100000
|
|
|
|
#define RS_CLIENT_HANDLE_MAX 0x100000 // Must be power of two
|
|
#define RS_CLIENT_HANDLE_BUCKET_COUNT 0x400 // 1024
|
|
#define RS_CLIENT_HANDLE_BUCKET_MASK 0x3FF
|
|
|
|
|
|
/// The default maximum number of domains a resource server can allocate
|
|
#define RS_MAX_DOMAINS_DEFAULT 4096
|
|
|
|
/// The maximum length of a line of ancestry for resource references
|
|
#define RS_MAX_RESOURCE_DEPTH 6
|
|
|
|
/// RS_LOCK_FLAGS
|
|
#define RS_LOCK_FLAGS_NO_TOP_LOCK NVBIT(0)
|
|
#define RS_LOCK_FLAGS_NO_CLIENT_LOCK NVBIT(1)
|
|
#define RS_LOCK_FLAGS_NO_CUSTOM_LOCK_1 NVBIT(2)
|
|
#define RS_LOCK_FLAGS_NO_CUSTOM_LOCK_2 NVBIT(3)
|
|
#define RS_LOCK_FLAGS_NO_CUSTOM_LOCK_3 NVBIT(4)
|
|
#define RS_LOCK_FLAGS_NO_DEPENDANT_SESSION_LOCK NVBIT(5)
|
|
#define RS_LOCK_FLAGS_FREE_SESSION_LOCK NVBIT(6)
|
|
|
|
/// RS_LOCK_STATE
|
|
#define RS_LOCK_STATE_TOP_LOCK_ACQUIRED NVBIT(0)
|
|
#define RS_LOCK_STATE_CUSTOM_LOCK_1_ACQUIRED NVBIT(1)
|
|
#define RS_LOCK_STATE_CUSTOM_LOCK_2_ACQUIRED NVBIT(2)
|
|
#define RS_LOCK_STATE_CUSTOM_LOCK_3_ACQUIRED NVBIT(3)
|
|
#define RS_LOCK_STATE_ALLOW_RECURSIVE_RES_LOCK NVBIT(6)
|
|
#define RS_LOCK_STATE_CLIENT_LOCK_ACQUIRED NVBIT(7)
|
|
#define RS_LOCK_STATE_SESSION_LOCK_ACQUIRED NVBIT(8)
|
|
|
|
/// RS_LOCK_RELEASE
|
|
#define RS_LOCK_RELEASE_TOP_LOCK NVBIT(0)
|
|
#define RS_LOCK_RELEASE_CLIENT_LOCK NVBIT(1)
|
|
#define RS_LOCK_RELEASE_CUSTOM_LOCK_1 NVBIT(2)
|
|
#define RS_LOCK_RELEASE_CUSTOM_LOCK_2 NVBIT(3)
|
|
#define RS_LOCK_RELEASE_CUSTOM_LOCK_3 NVBIT(4)
|
|
#define RS_LOCK_RELEASE_SESSION_LOCK NVBIT(5)
|
|
|
|
/// API enumerations used for locking knobs
|
|
typedef enum
|
|
{
|
|
RS_LOCK_CLIENT =0,
|
|
RS_LOCK_TOP =1,
|
|
RS_LOCK_RESOURCE =2,
|
|
RS_LOCK_CUSTOM_3 =3,
|
|
} RS_LOCK_ENUM;
|
|
|
|
typedef enum
|
|
{
|
|
RS_API_ALLOC_CLIENT = 0,
|
|
RS_API_ALLOC_RESOURCE = 1,
|
|
RS_API_FREE_RESOURCE = 2,
|
|
RS_API_MAP = 3,
|
|
RS_API_UNMAP = 4,
|
|
RS_API_INTER_MAP = 5,
|
|
RS_API_INTER_UNMAP = 6,
|
|
RS_API_COPY = 7,
|
|
RS_API_SHARE = 8,
|
|
RS_API_CTRL = 9,
|
|
RS_API_MAX,
|
|
} RS_API_ENUM;
|
|
|
|
NV_STATUS indexAdd(RsIndex *pIndex, NvU32 index, RsResourceRef *pResourceRef);
|
|
NV_STATUS indexRemove(RsIndex *pIndex, NvU32 index, RsResourceRef *pResourceRef);
|
|
|
|
//
|
|
// Externs
|
|
//
|
|
/**
|
|
* NVOC wrapper for constructing resources of a given type
|
|
*
|
|
* @param[in] pAllocator Allocator for the resource object
|
|
* @param[in] pCallContext Caller context passed to resource constructor
|
|
* @param[inout] pParams Resource allocation parameters
|
|
* @param[out] ppResource New resource object
|
|
*/
|
|
extern NV_STATUS resservResourceFactory(PORT_MEM_ALLOCATOR *pAllocator, CALL_CONTEXT *pCallContext,
|
|
RS_RES_ALLOC_PARAMS_INTERNAL *pParams, RsResource **ppResource);
|
|
|
|
/**
|
|
* NVOC wrapper for constructing an application-specific client.
|
|
*/
|
|
extern NV_STATUS resservClientFactory(PORT_MEM_ALLOCATOR *pAllocator, RS_RES_ALLOC_PARAMS_INTERNAL *pParams, RsClient **ppRsClient);
|
|
|
|
/**
|
|
* Validate the UID/PID security token of the current user against a client's security token.
|
|
*
|
|
* This will be obsolete after phase 1.
|
|
*
|
|
* @param[in] pClientToken
|
|
* @param[in] pCurrentToken
|
|
*
|
|
* @returns NV_OK if the current user's security token matches the client's security token
|
|
*/
|
|
extern NV_STATUS osValidateClientTokens(PSECURITY_TOKEN pClientToken, PSECURITY_TOKEN pCurrentToken);
|
|
|
|
/**
|
|
* Get the security token of the current user for the UID/PID security model.
|
|
*
|
|
* This will be obsolete after phase 1.
|
|
*/
|
|
extern PSECURITY_TOKEN osGetSecurityToken(void);
|
|
|
|
/**
|
|
* TLS entry id for call contexts. All servers will use the same id.
|
|
*/
|
|
#define TLS_ENTRY_ID_RESSERV_CALL_CONTEXT TLS_ENTRY_ID_RESSERV_1
|
|
|
|
//
|
|
// Structs
|
|
//
|
|
struct RS_FREE_STACK
|
|
{
|
|
RS_FREE_STACK *pPrev;
|
|
RsResourceRef *pResourceRef;
|
|
};
|
|
|
|
struct CALL_CONTEXT
|
|
{
|
|
RsServer *pServer; ///< The resource server instance that owns the client
|
|
RsClient *pClient; ///< Client that was the target of the call
|
|
RsResourceRef *pResourceRef; ///< Reference that was the target of the call
|
|
RsResourceRef *pContextRef; ///< Reference that may be used to provide more context [optional]
|
|
RS_LOCK_INFO *pLockInfo; ///< Saved locking context information for the call
|
|
API_SECURITY_INFO secInfo;
|
|
RS_RES_CONTROL_PARAMS_INTERNAL *pControlParams; ///< parameters of the call [optional]
|
|
};
|
|
|
|
typedef enum {
|
|
RS_ITERATE_CHILDREN, ///< Iterate over a RsResourceRef's children
|
|
RS_ITERATE_DESCENDANTS, ///< Iterate over a RsResourceRef's children, grandchildren, etc. (unspecified order)
|
|
RS_ITERATE_CACHED, ///< Iterate over a RsResourceRef's cache
|
|
RS_ITERATE_DEPENDANTS, ///< Iterate over a RsResourceRef's dependants
|
|
} RS_ITER_TYPE;
|
|
|
|
typedef enum
|
|
{
|
|
LOCK_ACCESS_READ,
|
|
LOCK_ACCESS_WRITE,
|
|
} LOCK_ACCESS_TYPE;
|
|
|
|
|
|
|
|
/**
|
|
* Access control information. This information will be filled out by the user
|
|
* of the Resource Server when allocating a client or resource.
|
|
*/
|
|
struct ACCESS_CONTROL
|
|
{
|
|
/**
|
|
* The privilege level of this access control
|
|
*/
|
|
RS_PRIV_LEVEL privilegeLevel;
|
|
|
|
/**
|
|
* Opaque pointer for storing a security token
|
|
*/
|
|
PSECURITY_TOKEN pSecurityToken;
|
|
};
|
|
|
|
//
|
|
// Utility wrappers for locking validator
|
|
//
|
|
#if LOCK_VAL_ENABLED
|
|
#define RS_LOCK_VALIDATOR_INIT(lock, lockClass, inst) \
|
|
do { NV_ASSERT_OK(lockvalLockInit((lock), (lockClass), (inst))); } while(0)
|
|
|
|
#define RS_RWLOCK_ACQUIRE_READ(lock, validator) do \
|
|
{ \
|
|
NV_ASSERT_OK(lockvalPreAcquire((validator))); \
|
|
portSyncRwLockAcquireRead((lock)); \
|
|
lockvalPostAcquire((validator), LOCK_VAL_RLOCK); \
|
|
} while(0)
|
|
|
|
#define RS_RWLOCK_ACQUIRE_WRITE(lock, validator) do \
|
|
{ \
|
|
NV_ASSERT_OK(lockvalPreAcquire((validator))); \
|
|
portSyncRwLockAcquireWrite((lock)); \
|
|
lockvalPostAcquire((validator), LOCK_VAL_WLOCK); \
|
|
} while(0)
|
|
|
|
#define RS_RWLOCK_RELEASE_READ_EXT(lock, validator, bOutOfOrder) do \
|
|
{ \
|
|
void *pLockValTlsEntry, *pReleasedLockNode; \
|
|
if (bOutOfOrder) \
|
|
NV_ASSERT_OK(lockvalReleaseOutOfOrder((validator), LOCK_VAL_RLOCK, &pLockValTlsEntry, &pReleasedLockNode)); \
|
|
else \
|
|
NV_ASSERT_OK(lockvalRelease((validator), LOCK_VAL_RLOCK, &pLockValTlsEntry, &pReleasedLockNode)); \
|
|
portSyncRwLockReleaseRead((lock)); \
|
|
lockvalMemoryRelease(pLockValTlsEntry, pReleasedLockNode); \
|
|
} while(0)
|
|
|
|
#define RS_RWLOCK_RELEASE_WRITE_EXT(lock, validator, bOutOfOrder) do \
|
|
{ \
|
|
void *pLockValTlsEntry, *pReleasedLockNode; \
|
|
if (bOutOfOrder) \
|
|
NV_ASSERT_OK(lockvalReleaseOutOfOrder((validator), LOCK_VAL_WLOCK, &pLockValTlsEntry, &pReleasedLockNode)); \
|
|
else \
|
|
NV_ASSERT_OK(lockvalRelease((validator), LOCK_VAL_WLOCK, &pLockValTlsEntry, &pReleasedLockNode)); \
|
|
portSyncRwLockReleaseWrite((lock)); \
|
|
lockvalMemoryRelease(pLockValTlsEntry, pReleasedLockNode); \
|
|
} while(0)
|
|
|
|
#else
|
|
#define RS_LOCK_VALIDATOR_INIT(lock, lockClass, inst)
|
|
#define RS_RWLOCK_ACQUIRE_READ(lock, validator) do { portSyncRwLockAcquireRead((lock)); } while(0)
|
|
#define RS_RWLOCK_ACQUIRE_WRITE(lock, validator) do { portSyncRwLockAcquireWrite((lock)); } while(0)
|
|
#define RS_RWLOCK_RELEASE_READ_EXT(lock, validator, bOutOfOrder) do { portSyncRwLockReleaseRead((lock)); } while(0)
|
|
#define RS_RWLOCK_RELEASE_WRITE_EXT(lock, validator, bOutOfOrder) do { portSyncRwLockReleaseWrite((lock)); } while(0)
|
|
#endif
|
|
|
|
#define RS_RWLOCK_RELEASE_READ(lock, validator) RS_RWLOCK_RELEASE_READ_EXT(lock, validator, NV_FALSE)
|
|
#define RS_RWLOCK_RELEASE_WRITE(lock, validator) RS_RWLOCK_RELEASE_WRITE_EXT(lock, validator, NV_FALSE)
|
|
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif
|