/* * SPDX-FileCopyrightText: Copyright (c) 2004-2022 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. */ #ifndef _CONTROL_H_ #define _CONTROL_H_ #include "core/core.h" #include "resserv/rs_resource.h" #include "resserv/resserv.h" #include "utils/nvmacro.h" #include "rmapi/param_copy.h" struct NVOC_EXPORTED_METHOD_DEF; typedef RS_RES_CONTROL_PARAMS_INTERNAL RmCtrlParams; // // RmCtrlExecuteCookie // // This typedef describes the data used by the rmctrl cmd execution // path. The data is filled at the beginning of rmControlCmdExecute() // and used as necessary in the other stages. // struct RS_CONTROL_COOKIE { // Rmctrl Command ID NvU32 cmd; // Rmctrl Flags NvU32 ctrlFlags; // Required Access Rights for this command const RS_ACCESS_MASK rightsRequired; NvBool bFreeParamCopy; ///< Indicates that param copies should be cleaned up NvBool bFreeEmbeddedCopy; ///< Indicates embedded param copies should be cleaned up RMAPI_PARAM_COPY paramCopy; RMAPI_PARAM_COPY embeddedParamCopies[4]; // Up to 4 embedded pointers per one RmControl identified }; typedef RS_CONTROL_COOKIE RmCtrlExecuteCookie; // values for RmCtrlDeferredCmd.pending #define RMCTRL_DEFERRED_FREE 0 // buffer is free #define RMCTRL_DEFERRED_ACQUIRED 1 // buffer is acquired to fill in data #define RMCTRL_DEFERRED_READY 2 // buffer is acquired and data has been copied. #define RMCTRL_DEFERRED_MAX_PARAM_SIZE 128 // 128 bytes internal buffer for rmctrl param typedef struct { NvS32 volatile pending; NvU32 cpuInst; RmCtrlParams rmCtrlDeferredParams; NvU8 paramBuffer[RMCTRL_DEFERRED_MAX_PARAM_SIZE]; // buffer to hold rmCtrlDeferredParams.pParams } RmCtrlDeferredCmd; // catch commands misdirected to non-existent engines #define VERIFY_OBJ_PTR(p) if (p == NULL) return NV_ERR_INVALID_ARGUMENT // macros to get/set/clear cap bits #define RMCTRL_GET_CAP(tbl,cap,field) (((NvU8)tbl[((1?cap##field)>=cap##_TBL_SIZE) ? 0/0 : (1?cap##field)]) & (0?cap##field)) #define RMCTRL_SET_CAP(tbl,cap,field) ((tbl[((1?cap##field)>=cap##_TBL_SIZE) ? 0/0 : (1?cap##field)]) |= (0?cap##field)) #define RMCTRL_CLEAR_CAP(tbl,cap,field) ((tbl[((1?cap##field)>=cap##_TBL_SIZE) ? 0/0 : (1?cap##field)]) &= ~(0?cap##field)) // macros to AND/OR caps between two tables #define RMCTRL_AND_CAP(finaltbl,tmptbl,tmp,cap,field) \ tmp = ((finaltbl[((1?cap##field)>=cap##_TBL_SIZE) ? 0/0 : (1?cap##field)] & tmptbl[((1?cap##field)>=cap##_TBL_SIZE) ? 0/0 : (1?cap##field)]) & (0?cap##field)); \ finaltbl[((1?cap##field)>=cap##_TBL_SIZE) ? 0/0 : (1?cap##field)] &= ~(0?cap##field); \ finaltbl[((1?cap##field)>=cap##_TBL_SIZE) ? 0/0 : (1?cap##field)] |= tmp; #define RMCTRL_OR_CAP(finaltbl,tmptbl,tmp,cap,field) \ tmp = ((finaltbl[((1?cap##field)>=cap##_TBL_SIZE) ? 0/0 : (1?cap##field)] | tmptbl[((1?cap##field)>=cap##_TBL_SIZE) ? 0/0 : (1?cap##field)]) & (0?cap##field)); \ finaltbl[((1?cap##field)>=cap##_TBL_SIZE) ? 0/0 : (1?cap##field)] &= ~(0?cap##field); \ finaltbl[((1?cap##field)>=cap##_TBL_SIZE) ? 0/0 : (1?cap##field)] |= tmp; // Whether the command ID is a NULL command? // We allow NVXXXX_CTRL_CMD_NULL (0x00000000) as well as the // per-class NULL cmd ( _CATEGORY==0x00 and _INDEX==0x00 ) #define RMCTRL_IS_NULL_CMD(cmd) ((cmd == NVXXXX_CTRL_CMD_NULL) || \ (FLD_TEST_DRF_NUM(XXXX, _CTRL_CMD, _CATEGORY, 0x00, cmd) && \ FLD_TEST_DRF_NUM(XXXX, _CTRL_CMD, _INDEX, 0x00, cmd))) // top-level internal RM Control interface NV_STATUS rmControl_Deferred(RmCtrlDeferredCmd *pRmCtrlDeferredCmd); // Helper functions for handling embedded parameter copies NV_STATUS embeddedParamCopyIn(RMAPI_PARAM_COPY *pParamCopy, RmCtrlParams *pRmCtrlParams); NV_STATUS embeddedParamCopyOut(RMAPI_PARAM_COPY *pParamCopy, RmCtrlParams *pRmCtrlParams); #define RM_CLIENT_PTR_ACCESS_CHECK_READ NVBIT(0) #define RM_CLIENT_PTR_ACCESS_CHECK_WRITE NVBIT(1) // // For NVOC Exported functions // // RMCTRL_FLAGS(A, B, C) is expanded to // 0 | RMCTRL_FLAGS_A | RMCTRL_FLAGS_B | RMCTRL_FLAGS_C // // ACCESS_RIGHTS(A, B, C) is expanded to // 0 | NVBIT(RS_ACCESS_A) | NVBIT(RS_ACCESS_B) | NVBIT(RS_ACCESS_C) // #define RMCTRL_EXPORT(cmdId, ...) [[nvoc::export(cmdId, __VA_ARGS__)]] #define _RMCTRL_PREP_FLAG_ARG(x) | NV_CONCATENATE(RMCTRL_FLAGS_, x) #define RMCTRL_FLAGS(...) (0 NV_FOREACH_ARG_NOCOMMA(_RMCTRL_PREP_FLAG_ARG, __VA_ARGS__)) #define _RMCTRL_PREP_ACCESS_ARG(x) | NVBIT(NV_CONCATENATE(RS_ACCESS_, x)) #define ACCESS_RIGHTS(...) (0 NV_FOREACH_ARG_NOCOMMA(_RMCTRL_PREP_ACCESS_ARG, __VA_ARGS__)) #define NVOC_EXPORTED_METHOD_DISABLED_BY_FLAG(ctrlFlags) \ ( \ (ctrlFlags & RMCTRL_FLAGS_ROUTE_TO_PHYSICAL) && \ !RMCFG_FEATURE_PHYSICAL_RM \ ) // // 'FLAGS' Attribute // ----------------- // // RMCTRL_FLAGS is used to specify per-command state. // #define RMCTRL_FLAGS_NONE 0x000000000 // // If the KERNEL_PRIVILEGED flag is specified, the call will only be allowed // for kernel mode callers (such as other kernel drivers) using a privileged // kernel RM client (CliCheckIsKernelClient() returning true). Otherwise, // NV_ERR_INSUFFICIENT_PERMISSIONS is returned. // #define RMCTRL_FLAGS_KERNEL_PRIVILEGED 0x000000000 // // The resman rmcontrol handler will not grab the "gpus lock" // before executing the implementing function. // // Please be sure you know what you're doing before using this! // #define RMCTRL_FLAGS_NO_GPUS_LOCK 0x000000001 // // Indicate to resman that this rmcontrol does not access any gpu // resources and can therefore run even when the gpu is powered down. // // Please be sure you know what you're doing before using this! // #define RMCTRL_FLAGS_NO_GPUS_ACCESS 0x000000002 // // If the PRIVILEGED flag is specified, the call will only be allowed for // a) user contexts with admin privleges (osIsAdministrator() returning true), or // b) kernel mode callers, such as other kernel drivers. // Otherwise, NV_ERR_INSUFFICIENT_PERMISSIONS is returned. // #define RMCTRL_FLAGS_PRIVILEGED 0x000000004 // // If the NON_PRIVILEGED flag is specified, the call will be allowed from any // client. // #define RMCTRL_FLAGS_NON_PRIVILEGED 0x000000010 // // The resman rmcontrol handler will grab the per-device lock instead // of the "gpus lock" before executing the implementing function. // // Please be sure you know what you're doing before using this! // #define RMCTRL_FLAGS_GPU_LOCK_DEVICE_ONLY 0x000000040 // // This flag is equivalent to PRIVILEGED when the RM access rights // implementation is disabled. Otherwise, it has no effect. // // The purpose of this flag is to aid in the transition to the access rights // system, so that access rights can be used for control calls that were // previously PRIVILEGED. Once access rights are enabled, this flag will no // longer be necessary. // #define RMCTRL_FLAGS_PRIVILEGED_IF_RS_ACCESS_DISABLED 0x000000100 // for Resserv Access Rights migration // // This flag specifies that the control shall be directly forwarded to the // physical object if called on the CPU-RM kernel. // #define RMCTRL_FLAGS_ROUTE_TO_PHYSICAL 0x000000200 // // If the INTERNAL flag is specified, the call will only be allowed // to be issued from RM itself. Otherwise, NV_ERR_NOT_SUPPORTED is returned. // #define RMCTRL_FLAGS_INTERNAL 0x000000400 // // If the API_LOCK_READONLY flag is specified, the call will acquire the // read-only API lock and may run concurrently with other operations that have // also taken the read-only API lock. This flag is ignored if read-only API // locking is disabled in RM. // #define RMCTRL_FLAGS_API_LOCK_READONLY 0x000000800 // // If the :GPU_LOCK_READONLY flag is specified, the call will acquire a // read-only GPU lock and may run concurrently with other operations that have // also taken a read-only GPU lock. This flag is ignored if read-only GPU // locking is disabled in RM. // #define RMCTRL_FLAGS_GPU_LOCK_READONLY 0x000001000 // // This flag specifies that the control shall be directly forwarded to the // the VGPU host if called from a guest (where IS_VIRTUAL() is true) // #define RMCTRL_FLAGS_ROUTE_TO_VGPU_HOST 0x000002000 // // This flag specifies that the control output does not depend on the input // parameters and can be cached on the receiving end. // The cache is transparent and may not exist on all platforms. // #define RMCTRL_FLAGS_CACHEABLE 0x000004000 // // This flag specifies that the control parameters will be // copied out back to the caller even if the control call fails. // #define RMCTRL_FLAGS_COPYOUT_ON_ERROR 0x000008000 // ?? #define RMCTRL_FLAGS_ALLOW_WITHOUT_SYSMEM_ACCESS 0x000010000 // // 'ACCESS_RIGHTS' Attribute // ------------------------ // // Used to specify a set of access rights that the client must hold on the // target resource to execute this control call. Note that this can only check // access rights on the target object; for other objects, such as those // specified by handles in parameter structs, checks must be done manually. // // The definition of each access right and its meaning is provided in the // README located at drivers/common/shared/accessrights/README. The prefix // "RS_ACCESS" is appended to each entry in the control call definition; // for example, :NICE -> RS_ACCESS_NICE. // // This attribute only has an effect when the RM access rights implementation // is enabled; see g_bRsAccessEnabled. // #endif // _CONTROL_H_