1 /* 2 * SPDX-FileCopyrightText: Copyright (c) 2019-2023 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 /****************************************************************************** 25 * 26 * Description: 27 * This file contains the functions managing MIG compute instance subscriptions 28 * 29 *****************************************************************************/ 30 31 #define NVOC_COMPUTE_INSTANCE_SUBSCRIPTION_H_PRIVATE_ACCESS_ALLOWED 32 33 #include "core/core.h" 34 #include "gpu/gpu.h" 35 #include "core/system.h" 36 #include "os/os.h" 37 #include "gpu/subdevice/subdevice.h" 38 39 #include "kernel/gpu/mig_mgr/gpu_instance_subscription.h" 40 #include "kernel/gpu/mig_mgr/compute_instance_subscription.h" 41 #include "kernel/gpu/mig_mgr/kernel_mig_manager.h" 42 43 #include "class/clc638.h" 44 #include "rmapi/rs_utils.h" 45 #include "gpu/gpu_uuid.h" 46 #include "vgpu/rpc.h" 47 48 NV_STATUS 49 cisubscriptionConstruct_IMPL 50 ( 51 ComputeInstanceSubscription *pComputeInstanceSubscription, 52 CALL_CONTEXT *pCallContext, 53 RS_RES_ALLOC_PARAMS_INTERNAL *pRmAllocParams 54 ) 55 { 56 NVC638_ALLOCATION_PARAMETERS *pUserParams = pRmAllocParams->pAllocParams; 57 RsClient *pRsClient = pCallContext->pClient; 58 RsResourceRef *pResourceRef = pCallContext->pResourceRef; 59 RsResourceRef *pParentRef = pResourceRef->pParentRef; 60 GPUInstanceSubscription *pGPUInstanceSubscription = dynamicCast(pParentRef->pResource, GPUInstanceSubscription); 61 OBJGPU *pGpu; 62 MIG_COMPUTE_INSTANCE *pMIGComputeInstance; 63 NV_STATUS status; 64 65 pGpu = GPU_RES_GET_GPU(pComputeInstanceSubscription); 66 67 osRmCapInitDescriptor(&pComputeInstanceSubscription->dupedCapDescriptor); 68 69 if (RS_IS_COPY_CTOR(pRmAllocParams)) 70 return cisubscriptionCopyConstruct_IMPL(pComputeInstanceSubscription, pCallContext, pRmAllocParams); 71 72 if (!IS_MIG_IN_USE(pGpu)) 73 { 74 NV_ASSERT_FAILED("Compute instance Subscription failed: MIG GPU partitioning not done"); 75 return NV_ERR_NOT_SUPPORTED; 76 } 77 78 NV_CHECK_OR_RETURN(LEVEL_SILENT, pUserParams->execPartitionId < KMIGMGR_MAX_COMPUTE_INSTANCES, NV_ERR_INVALID_ARGUMENT); 79 NV_CHECK_OR_RETURN(LEVEL_SILENT, gisubscriptionGetMIGGPUInstance(pGPUInstanceSubscription) != NULL, NV_ERR_INVALID_STATE); 80 NV_CHECK_OR_RETURN(LEVEL_SILENT, gisubscriptionGetMIGGPUInstance(pGPUInstanceSubscription)->bValid, NV_ERR_INVALID_STATE); 81 82 pMIGComputeInstance = &gisubscriptionGetMIGGPUInstance(pGPUInstanceSubscription)->MIGComputeInstance[pUserParams->execPartitionId]; 83 NV_CHECK_OR_RETURN(LEVEL_SILENT, pMIGComputeInstance->bValid, NV_ERR_INVALID_ARGUMENT); 84 85 // 86 // For now skip kernel clients, such as UVM, until Bug 2729768 is fixed. 87 // 88 if (pRsClient->type == CLIENT_TYPE_USER) 89 { 90 status = osRmCapAcquire(pMIGComputeInstance->pOsRmCaps, 91 NV_RM_CAP_SMC_EXEC_PARTITION_ACCESS, 92 pUserParams->capDescriptor, 93 &pComputeInstanceSubscription->dupedCapDescriptor); 94 if ((status != NV_ERR_NOT_SUPPORTED) && (status != NV_OK)) 95 { 96 NV_PRINTF(LEVEL_ERROR, 97 "Capability validation failed: ID 0x%0x!\n", 98 pUserParams->execPartitionId); 99 return status; 100 } 101 } 102 103 pComputeInstanceSubscription->pMIGComputeInstance = pMIGComputeInstance; 104 105 NV_ASSERT_OK_OR_GOTO(status, 106 kmigmgrIncRefCount(pMIGComputeInstance->pShare), 107 cleanup_duped_desc); 108 109 return NV_OK; 110 111 cleanup_duped_desc: 112 osRmCapRelease(pComputeInstanceSubscription->dupedCapDescriptor); 113 114 return status; 115 } 116 117 NV_STATUS 118 cisubscriptionCopyConstruct_IMPL 119 ( 120 ComputeInstanceSubscription *pComputeInstanceSubscription, 121 CALL_CONTEXT *pCallContext, 122 RS_RES_ALLOC_PARAMS_INTERNAL *pParams 123 ) 124 { 125 RsResourceRef *pSrcRef = pParams->pSrcRef; 126 ComputeInstanceSubscription *pComputeInstanceSubscriptionSrc = dynamicCast(pSrcRef->pResource, ComputeInstanceSubscription); 127 OBJGPU *pGpu = GPU_RES_GET_GPU(pComputeInstanceSubscription); 128 129 // non kernel clients are not allowed to dup MIG instances 130 NV_CHECK_OR_RETURN(LEVEL_SILENT, pCallContext->secInfo.privLevel >= RS_PRIV_LEVEL_KERNEL, 131 NV_ERR_NOT_SUPPORTED); 132 133 if (IS_VIRTUAL_WITH_SRIOV(pGpu) || IS_GSP_CLIENT(pGpu)) 134 { 135 RsResourceRef *pDstRef = pCallContext->pResourceRef; 136 NV_STATUS status = NV_OK; 137 138 NV_RM_RPC_DUP_OBJECT(pGpu, 139 pCallContext->pClient->hClient, 140 pDstRef->pParentRef->hResource, 141 pDstRef->hResource, 142 pParams->pSrcClient->hClient, 143 pSrcRef->hResource, 144 0, NV_TRUE, // Send RPC for object free 145 pDstRef, status); 146 NV_CHECK_OK_OR_RETURN(LEVEL_ERROR, status); 147 } 148 149 pComputeInstanceSubscription->pMIGComputeInstance = pComputeInstanceSubscriptionSrc->pMIGComputeInstance; 150 151 NV_ASSERT_OK( 152 kmigmgrIncRefCount(pComputeInstanceSubscription->pMIGComputeInstance->pShare)); 153 154 return NV_OK; 155 } 156 157 void 158 cisubscriptionDestruct_IMPL 159 ( 160 ComputeInstanceSubscription *pComputeInstanceSubscription 161 ) 162 { 163 CALL_CONTEXT *pCallContext; 164 RS_RES_FREE_PARAMS_INTERNAL *pParams; 165 166 resGetFreeParams(staticCast(pComputeInstanceSubscription, RsResource), &pCallContext, &pParams); 167 168 osRmCapRelease(pComputeInstanceSubscription->dupedCapDescriptor); 169 170 gisubscriptionCleanupOnUnsubscribe(pCallContext); 171 172 NV_ASSERT_OK( 173 kmigmgrDecRefCount(pComputeInstanceSubscription->pMIGComputeInstance->pShare)); 174 } 175 176 NV_STATUS 177 cisubscriptionGetComputeInstanceSubscription_IMPL 178 ( 179 RsClient *pClient, 180 NvHandle hParent, 181 ComputeInstanceSubscription **ppComputeInstanceSubscription 182 ) 183 { 184 RsResourceRef *pResourceRef; 185 186 NV_ASSERT_OR_RETURN(ppComputeInstanceSubscription != NULL, NV_ERR_INVALID_ARGUMENT); 187 188 pResourceRef = serverutilFindChildRefByType(pClient->hClient, 189 hParent, classId(ComputeInstanceSubscription), 190 NV_TRUE); 191 if (pResourceRef == NULL) 192 return NV_ERR_OBJECT_NOT_FOUND; 193 194 *ppComputeInstanceSubscription = dynamicCast(pResourceRef->pResource, ComputeInstanceSubscription); 195 196 return NV_OK; 197 } 198 199 NvBool 200 cisubscriptionCanCopy_IMPL 201 ( 202 ComputeInstanceSubscription *pComputeInstanceSubscription 203 ) 204 { 205 return NV_TRUE; 206 } 207 208 NV_STATUS 209 cisubscriptionCtrlCmdGetUuid_IMPL 210 ( 211 ComputeInstanceSubscription *pComputeInstanceSubscription, 212 NVC638_CTRL_GET_UUID_PARAMS *pParams 213 ) 214 { 215 ct_assert(NV_UUID_LEN == NVC638_UUID_LEN); 216 ct_assert(NV_UUID_STR_LEN == NVC638_UUID_STR_LEN); 217 218 portMemCopy(pParams->uuid, NVC638_UUID_LEN, 219 pComputeInstanceSubscription->pMIGComputeInstance->uuid.uuid, NV_UUID_LEN); 220 221 nvGetSmcUuidString(&pComputeInstanceSubscription->pMIGComputeInstance->uuid, 222 pParams->uuidStr); 223 224 return NV_OK; 225 } 226