1 /* 2 * SPDX-FileCopyrightText: Copyright (c) 2012-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 #include "ctrl/ctrla081.h" 25 #include "class/clc637.h" // for AMPERE_SMC_PARTITION_REF 26 #include "virtualization/kernel_hostvgpudeviceapi.h" 27 28 #include "core/system.h" 29 #include "os/os.h" 30 #include "rmapi/control.h" 31 #include "virtualization/hypervisor/hypervisor.h" 32 #include "virtualization/kernel_vgpu_mgr.h" 33 #include "gpu/device/device.h" 34 #include "vgpu/vgpu_version.h" 35 #include "rmapi/rmapi_utils.h" 36 #include "rmapi/rs_utils.h" 37 #include "gpu/gpu.h" 38 #include "gpu/mem_sys/kern_mem_sys.h" 39 #include "gpu/mem_mgr/mem_mgr.h" 40 #include "gpu/mem_mgr/heap.h" 41 #include "kernel/gpu/mig_mgr/kernel_mig_manager.h" 42 #include "nvdevid.h" 43 44 #define __VGPU_ALIAS_PGPU_LIST__ 45 #include "g_vgpu_resman_specific.h" // _get_chip_id_for_alias_pgpu 46 #undef __VGPU_ALIAS_PGPU_LIST__ 47 48 #define MAX_NVU32_TO_CONVERTED_STR_LEN 0x8 49 50 #define DEVID_ENCODED_VALUE_SIZE 0x4 51 #define SUBDEVID_ENCODED_VALUE_SIZE 0x4 52 #define PGPU_CAP_ENCODED_VALUE_SIZE 0x8 53 54 #define PGPU_CAP_ECC_ON (1 << 0) 55 #define PGPU_CAP_SRIOV_ON (1 << 1) 56 57 #define VGPU_LOWER_FB_PROFILE_SIZE_1_GB (1024 * 1024 * 1024) 58 59 // Mapping of vGPU MIG profiles types to corresponding RM partiotionFlag 60 #define GENERATE_vgpuSmcTypeIdMappings 61 #include "g_vgpu_resman_specific.h" 62 #undef GENERATE_vgpuSmcTypeIdMappings 63 // 64 // ODB functions 65 // 66 67 NV_STATUS 68 kvgpumgrConstruct_IMPL(KernelVgpuMgr *pKernelVgpuMgr) 69 { 70 NV_PRINTF(LEVEL_INFO, "Enter function\n"); 71 72 pKernelVgpuMgr->pHeap = NULL; 73 74 /* Default vGPU version is set to the host supported vGPU version range */ 75 pKernelVgpuMgr->user_min_supported_version 76 = GRIDSW_VERSION_EXTERNAL(NV_VGPU_MIN_SUPPORTED_GRIDSW_VERSION_EXTERNAL_MAJOR, 77 NV_VGPU_MIN_SUPPORTED_GRIDSW_VERSION_EXTERNAL_MINOR); 78 pKernelVgpuMgr->user_max_supported_version 79 = GRIDSW_VERSION_EXTERNAL(NV_VGPU_MAX_SUPPORTED_GRIDSW_VERSION_EXTERNAL_MAJOR, 80 NV_VGPU_MAX_SUPPORTED_GRIDSW_VERSION_EXTERNAL_MINOR); 81 82 listInit(&(pKernelVgpuMgr->listVgpuTypeHead), portMemAllocatorGetGlobalNonPaged()); 83 listInit(&(pKernelVgpuMgr->listVgpuGuestHead), portMemAllocatorGetGlobalNonPaged()); 84 listInit(&(pKernelVgpuMgr->listRequestVgpuHead), portMemAllocatorGetGlobalNonPaged()); 85 86 return NV_OK; 87 } 88 89 void 90 kvgpumgrDestruct_IMPL(KernelVgpuMgr *pKernelVgpuMgr) 91 { 92 if (pKernelVgpuMgr->pHeap != NULL) 93 { 94 pKernelVgpuMgr->pHeap->eheapDestruct(pKernelVgpuMgr->pHeap); 95 portMemFree(pKernelVgpuMgr->pHeap); 96 } 97 98 listDestroy(&(pKernelVgpuMgr->listRequestVgpuHead)); 99 listDestroy(&(pKernelVgpuMgr->listVgpuTypeHead)); 100 listDestroy(&(pKernelVgpuMgr->listVgpuGuestHead)); 101 } 102 103 // 104 // Get max instance for a vgpu profile. 105 // 106 NV_STATUS 107 kvgpumgrGetMaxInstanceOfVgpu(NvU32 vgpuTypeId, NvU32 *maxInstanceVgpu) 108 { 109 VGPU_TYPE *vgpuTypeInfo; 110 NV_STATUS status; 111 112 if (maxInstanceVgpu == NULL) 113 { 114 return NV_ERR_INVALID_ARGUMENT; 115 } 116 117 status = kvgpumgrGetVgpuTypeInfo(vgpuTypeId, &vgpuTypeInfo); 118 if (status == NV_OK) 119 { 120 *maxInstanceVgpu = vgpuTypeInfo->maxInstance; 121 } 122 123 return status; 124 } 125 126 // 127 // vGPU Manager functions 128 // 129 130 static NV_STATUS 131 _kvgpumgrGetVgpuTypeIdFromPartitionFlag(NvU32 devId, NvU32 partitionFlag, NvU32 *vgpuTypeId); 132 133 static NV_STATUS 134 _kvgpumgrClearAssignedSwizzIdMask(OBJGPU *pGpu, 135 NvU32 swizzId); 136 137 static NV_STATUS 138 _kvgpumgrUpdateCreatablePlacementIds(OBJGPU *pGpu, NvU16 placementId, 139 NvU32 vgpuTypeId, NvBool isVmBoot); 140 141 NV_STATUS 142 kvgpumgrGetPgpuIndex(KernelVgpuMgr *pKernelVgpuMgr, NvU32 gpuPciId, NvU32* index) 143 { 144 NvU32 i; 145 for (i = 0; i < NV_ARRAY_ELEMENTS(pKernelVgpuMgr->pgpuInfo); i++) 146 { 147 if ((pKernelVgpuMgr->pgpuInfo[i].gpuPciId == gpuPciId) && 148 (pKernelVgpuMgr->pgpuInfo[i].isAttached == NV_TRUE)) 149 { 150 *index = i; 151 return NV_OK; 152 } 153 } 154 return NV_ERR_OBJECT_NOT_FOUND; 155 } 156 157 NvBool 158 kvgpumgrIsHeterogeneousVgpuSupported(void) 159 { 160 /*This support is currently limited to VMware and KVM*/ 161 return (osIsVgpuVfioPresent() == NV_OK); 162 } 163 164 NV_STATUS 165 kvgpumgrSetVgpuType(OBJGPU *pGpu, KERNEL_PHYS_GPU_INFO *pPhysGpuInfo, NvU32 vgpuTypeId) 166 { 167 NvU32 i; 168 169 /* 170 * If heterogeneous timesliced mode is enabled, supportedTypeIds is already 171 * prepared when creatable placementIds array is updated in 172 * _kvgpumgrUpdateCreatablePlacementIds() function 173 */ 174 if (pGpu && pGpu->getProperty(pGpu, PDB_PROP_GPU_IS_VGPU_HETEROGENEOUS_MODE)) 175 return NV_OK; 176 177 for (i = 0; i < MAX_VGPU_TYPES_PER_PGPU; i++) 178 pPhysGpuInfo->supportedTypeIds[i] = NVA081_CTRL_VGPU_CONFIG_INVALID_TYPE; 179 180 if (vgpuTypeId == NVA081_CTRL_VGPU_CONFIG_INVALID_TYPE) 181 { 182 for (i = 0; i < pPhysGpuInfo->numVgpuTypes; i++) 183 pPhysGpuInfo->supportedTypeIds[i] = pPhysGpuInfo->vgpuTypes[i]->vgpuTypeId; 184 185 return NV_OK; 186 } 187 188 if (kvgpumgrIsHeterogeneousVgpuSupported()) 189 { 190 VGPU_TYPE *vgpuTypeInfo = NULL; 191 NV_STATUS status = kvgpumgrGetVgpuTypeInfo(vgpuTypeId, &vgpuTypeInfo); 192 NvU32 numSupported = 0; 193 194 if (status != NV_OK) 195 return status; 196 197 NvU64 totalFbAllocation = vgpuTypeInfo->profileSize; 198 199 for (i = 0; i < pPhysGpuInfo->numVgpuTypes; i++) 200 { 201 if (pPhysGpuInfo->vgpuTypes[i]->profileSize == totalFbAllocation) 202 { 203 pPhysGpuInfo->supportedTypeIds[numSupported] = pPhysGpuInfo->vgpuTypes[i]->vgpuTypeId; 204 numSupported++; 205 } 206 } 207 } 208 else 209 { 210 pPhysGpuInfo->supportedTypeIds[0] = vgpuTypeId; 211 } 212 213 return NV_OK; 214 } 215 216 static NV_STATUS 217 _kvgpumgrCheckVgpuTypeSupported(OBJGPU *pGpu, KERNEL_PHYS_GPU_INFO *pPhysGpuInfo, 218 VGPU_TYPE *vgpuTypeInfo, NvU32 existingVgpus) 219 { 220 NvU32 i; 221 222 if (existingVgpus == 0) 223 return NV_OK; 224 225 for (i = 0; i < pPhysGpuInfo->numVgpuTypes; i++) 226 { 227 if (pPhysGpuInfo->supportedTypeIds[i] == vgpuTypeInfo->vgpuTypeId) 228 break; 229 if (pPhysGpuInfo->supportedTypeIds[i] == NVA081_CTRL_VGPU_CONFIG_INVALID_TYPE) 230 return NV_ERR_NOT_SUPPORTED; 231 } 232 233 /* 234 * In heterogeneous vGPU mode, creatable vGPU type is not dependent on a vGPU types 235 * maxInstance. If the type is present in supportedTypeIds (populated based on placementIds), 236 * it should suffice 237 */ 238 if (!pGpu->getProperty(pGpu, PDB_PROP_GPU_IS_VGPU_HETEROGENEOUS_MODE)) 239 { 240 if (existingVgpus >= vgpuTypeInfo->maxInstance) 241 return NV_ERR_INSUFFICIENT_RESOURCES; 242 } 243 244 return NV_OK; 245 } 246 247 NV_STATUS 248 kvgpumgrCheckVgpuTypeCreatable(OBJGPU *pGpu, KERNEL_PHYS_GPU_INFO *pPhysGpuInfo, VGPU_TYPE *vgpuTypeInfo) 249 { 250 if (osIsVgpuVfioPresent() == NV_OK) 251 return _kvgpumgrCheckVgpuTypeSupported(pGpu, pPhysGpuInfo, vgpuTypeInfo, pPhysGpuInfo->numCreatedVgpu); 252 else 253 return _kvgpumgrCheckVgpuTypeSupported(pGpu, pPhysGpuInfo, vgpuTypeInfo, pPhysGpuInfo->numActiveVgpu); 254 } 255 256 static NV_STATUS 257 _kvgpumgrCheckVgpuTypeActivatable(OBJGPU *pGpu, KERNEL_PHYS_GPU_INFO *pPhysGpuInfo, VGPU_TYPE *vgpuTypeInfo) 258 { 259 return _kvgpumgrCheckVgpuTypeSupported(pGpu, pPhysGpuInfo, vgpuTypeInfo, pPhysGpuInfo->numActiveVgpu); 260 } 261 262 NV_STATUS 263 kvgpumgrGetCreatableVgpuTypes(OBJGPU *pGpu, KernelVgpuMgr *pKernelVgpuMgr, NvU32 pgpuIndex, NvU32* numVgpuTypes, NvU32* vgpuTypes) 264 { 265 NvU32 i = 0; 266 KERNEL_PHYS_GPU_INFO *pgpuInfo = &pKernelVgpuMgr->pgpuInfo[pgpuIndex]; 267 268 if (IS_MIG_ENABLED(pGpu)) 269 { 270 if (IS_MIG_IN_USE(pGpu)) 271 { 272 KernelMIGManager *pKernelMIGManager = GPU_GET_KERNEL_MIG_MANAGER(pGpu); 273 NvU64 swizzIdInUseMask = 0; 274 NvU32 id; 275 276 swizzIdInUseMask = kmigmgrGetSwizzIdInUseMask(pGpu, pKernelMIGManager); 277 278 i = 0; 279 FOR_EACH_INDEX_IN_MASK(64, id, swizzIdInUseMask) 280 { 281 KERNEL_MIG_GPU_INSTANCE *pKernelMIGGpuInstance; 282 NvU32 vgpuTypeId = NVA081_CTRL_VGPU_CONFIG_INVALID_TYPE; 283 NvU32 j, mask = 0; 284 285 mask = NVBIT64(id); 286 NV_ASSERT_OK_OR_RETURN(kmigmgrGetGPUInstanceInfo(pGpu, pKernelMIGManager, id, &pKernelMIGGpuInstance)); 287 288 // Do not consider vGPU type as creatable if swizzId is already in use 289 if (!(mask & pgpuInfo->assignedSwizzIdMask)) 290 { 291 // Find the vGPU type corresponding to the partitionFlag, 292 NV_ASSERT_OK_OR_RETURN( 293 _kvgpumgrGetVgpuTypeIdFromPartitionFlag(pGpu->idInfo.PCIDeviceID, 294 pKernelMIGGpuInstance->partitionFlag, 295 &vgpuTypeId)); 296 297 // Check if we have already included this vGPU type ID. 298 // If not, then add vgpuTypeID to out vgpuTypes array. 299 if (vgpuTypeId != NVA081_CTRL_VGPU_CONFIG_INVALID_TYPE) 300 { 301 for(j = 0; j < i; j++) 302 { 303 if (vgpuTypes[j] == vgpuTypeId) 304 { 305 break; 306 } 307 } 308 309 // vgpuTypeId not included in vgputypes array yet, include it. 310 if (j == i) 311 { 312 vgpuTypes[i] = vgpuTypeId; 313 i++; 314 } 315 } 316 } 317 } 318 FOR_EACH_INDEX_IN_MASK_END; 319 *numVgpuTypes = i; 320 } 321 else 322 { 323 // No GPU instances created, none of the profiles are creatable. 324 *numVgpuTypes = 0; 325 } 326 } 327 else 328 { 329 *numVgpuTypes = 0; 330 for (i = 0; i < pgpuInfo->numVgpuTypes; i++) 331 { 332 // Consider only non-MIG (gpuInstanceSize == 0) profiles 333 if (!pgpuInfo->vgpuTypes[i]->gpuInstanceSize && 334 (kvgpumgrCheckVgpuTypeCreatable(pGpu, pgpuInfo, pgpuInfo->vgpuTypes[i]) == NV_OK)) 335 { 336 vgpuTypes[*numVgpuTypes] = pgpuInfo->vgpuTypes[i]->vgpuTypeId; 337 (*numVgpuTypes)++; 338 } 339 } 340 } 341 342 return NV_OK; 343 } 344 345 static NV_STATUS 346 _kvgpumgrCreateVgpuType(NVA081_CTRL_VGPU_INFO *pVgpuInfo, VGPU_TYPE **ppVgpuType) 347 { 348 OBJSYS *pSys = SYS_GET_INSTANCE(); 349 KernelVgpuMgr *pKernelVgpuMgr = SYS_GET_KERNEL_VGPUMGR(pSys); 350 VGPU_TYPE *pVgpuTypeNode; 351 352 pVgpuTypeNode = listAppendNew(&(pKernelVgpuMgr->listVgpuTypeHead)); 353 if (pVgpuTypeNode == NULL) 354 return NV_ERR_NO_MEMORY; 355 356 vgpuMgrFillVgpuType(pVgpuInfo, pVgpuTypeNode); 357 358 *ppVgpuType = pVgpuTypeNode; 359 360 return NV_OK; 361 } 362 363 NV_STATUS 364 kvgpumgrGetVgpuTypeInfo(NvU32 vgpuTypeId, VGPU_TYPE **vgpuType) 365 { 366 OBJSYS *pSys = SYS_GET_INSTANCE(); 367 KernelVgpuMgr *pKernelVgpuMgr = SYS_GET_KERNEL_VGPUMGR(pSys); 368 VGPU_TYPE *pVgpuTypeNode; 369 370 for (pVgpuTypeNode = listHead(&(pKernelVgpuMgr->listVgpuTypeHead)); 371 pVgpuTypeNode != NULL; 372 pVgpuTypeNode = listNext(&(pKernelVgpuMgr->listVgpuTypeHead), pVgpuTypeNode)) 373 { 374 if (vgpuTypeId == pVgpuTypeNode->vgpuTypeId) 375 { 376 *vgpuType = pVgpuTypeNode; 377 return NV_OK; 378 } 379 } 380 return NV_ERR_OBJECT_NOT_FOUND; 381 } 382 383 static void 384 kvgpumgrCopyFromVgpuTypeToVgpuInfo(NVA081_CTRL_VGPU_INFO *pVgpuInfo, VGPU_TYPE *pVgpuType) 385 { 386 pVgpuInfo->vgpuType = pVgpuType->vgpuTypeId; 387 pVgpuInfo->maxInstance = pVgpuType->maxInstance; 388 pVgpuInfo->numHeads = pVgpuType->numHeads; 389 pVgpuInfo->maxResolutionX = pVgpuType->maxResolutionX; 390 pVgpuInfo->maxResolutionY = pVgpuType->maxResolutionY; 391 pVgpuInfo->maxPixels = pVgpuType->maxPixels; 392 pVgpuInfo->frlConfig = pVgpuType->frlConfig; 393 pVgpuInfo->cudaEnabled = pVgpuType->cudaEnabled; 394 pVgpuInfo->eccSupported = pVgpuType->eccSupported; 395 pVgpuInfo->gpuInstanceSize = pVgpuType->gpuInstanceSize; 396 pVgpuInfo->multiVgpuSupported = pVgpuType->multiVgpuSupported; 397 pVgpuInfo->vdevId = pVgpuType->vdevId; 398 pVgpuInfo->pdevId = pVgpuType->pdevId; 399 pVgpuInfo->profileSize = pVgpuType->profileSize; 400 pVgpuInfo->fbLength = pVgpuType->fbLength; 401 pVgpuInfo->gspHeapSize = pVgpuType->gspHeapSize; 402 pVgpuInfo->fbReservation = pVgpuType->fbReservation; 403 pVgpuInfo->mappableVideoSize = pVgpuType->mappableVideoSize; 404 pVgpuInfo->encoderCapacity = pVgpuType->encoderCapacity; 405 pVgpuInfo->bar1Length = pVgpuType->bar1Length; 406 pVgpuInfo->gpuDirectSupported = pVgpuType->gpuDirectSupported; 407 pVgpuInfo->nvlinkP2PSupported = pVgpuType->nvlinkP2PSupported; 408 pVgpuInfo->multiVgpuExclusive = pVgpuType->multiVgpuExclusive; 409 pVgpuInfo->frlEnable = pVgpuType->frlEnable; 410 411 portStringCopy( 412 (char *) pVgpuInfo->vgpuName, sizeof(pVgpuInfo->vgpuName), 413 (char *) pVgpuType->vgpuName, sizeof(pVgpuType->vgpuName)); 414 portStringCopy( 415 (char *) pVgpuInfo->vgpuClass, sizeof(pVgpuInfo->vgpuClass), 416 (char *) pVgpuType->vgpuClass, sizeof(pVgpuType->vgpuClass)); 417 portStringCopy( 418 (char *) pVgpuInfo->license, sizeof(pVgpuInfo->license), 419 (char *) pVgpuType->license, sizeof(pVgpuType->license)); 420 portStringCopy( 421 (char *) pVgpuInfo->vgpuExtraParams, sizeof(pVgpuInfo->vgpuExtraParams), 422 (char *) pVgpuType->vgpuExtraParams, sizeof(pVgpuType->vgpuExtraParams)); 423 portMemCopy( 424 (char *) pVgpuInfo->vgpuSignature, sizeof(pVgpuInfo->vgpuSignature), 425 (char *) pVgpuType->vgpuSignature, sizeof(pVgpuType->vgpuSignature)); 426 } 427 428 NV_STATUS 429 kvgpumgrSendAllVgpuTypesToGsp(OBJGPU *pGpu) 430 { 431 NV_STATUS rmStatus = NV_OK; 432 OBJSYS *pSys = SYS_GET_INSTANCE(); 433 KernelVgpuMgr *pKernelVgpuMgr = SYS_GET_KERNEL_VGPUMGR(pSys); 434 RM_API *pRmApi = GPU_GET_PHYSICAL_RMAPI(pGpu); 435 KERNEL_PHYS_GPU_INFO *pPgpuInfo; 436 NV2080_CTRL_VGPU_MGR_INTERNAL_PGPU_ADD_VGPU_TYPE_PARAMS *pAddVgpuTypeParams; 437 NvU32 index, i; 438 439 NV_CHECK_OK_OR_RETURN(LEVEL_ERROR, 440 kvgpumgrGetPgpuIndex(pKernelVgpuMgr, pGpu->gpuId, &index)); 441 442 pPgpuInfo = &(pKernelVgpuMgr->pgpuInfo[index]); 443 444 // Early exit if no vgpu types found 445 if (pPgpuInfo->numVgpuTypes == 0) 446 { 447 return NV_OK; 448 } 449 450 pAddVgpuTypeParams = portMemAllocNonPaged(sizeof(*pAddVgpuTypeParams)); 451 if (pAddVgpuTypeParams == NULL) 452 { 453 NV_PRINTF(LEVEL_ERROR, "Failed to alloc memory for add vGPU type params\n"); 454 return NV_ERR_NO_MEMORY; 455 } 456 457 portMemSet(pAddVgpuTypeParams, 0, sizeof(*pAddVgpuTypeParams)); 458 459 for (i = 0; i < pPgpuInfo->numVgpuTypes; i++) 460 { 461 kvgpumgrCopyFromVgpuTypeToVgpuInfo(&pAddVgpuTypeParams->vgpuInfo[i], 462 pPgpuInfo->vgpuTypes[i]); 463 } 464 465 pAddVgpuTypeParams->discardVgpuTypes = NV_TRUE; 466 pAddVgpuTypeParams->vgpuInfoCount = pPgpuInfo->numVgpuTypes; 467 468 NV_CHECK_OK_OR_GOTO(rmStatus, LEVEL_ERROR, 469 pRmApi->Control(pRmApi, pGpu->hInternalClient, pGpu->hInternalSubdevice, 470 NV2080_CTRL_CMD_VGPU_MGR_INTERNAL_PGPU_ADD_VGPU_TYPE, 471 pAddVgpuTypeParams, sizeof(*pAddVgpuTypeParams)), 472 kvgpumgrSendAllVgpuTypesToGsp_exit); 473 474 kvgpumgrSendAllVgpuTypesToGsp_exit: 475 portMemFree(pAddVgpuTypeParams); 476 return rmStatus; 477 } 478 479 NV_STATUS 480 kvgpumgrPgpuAddVgpuType 481 ( 482 OBJGPU *pGpu, 483 NvBool discardVgpuTypes, 484 NVA081_CTRL_VGPU_INFO *pVgpuInfo 485 ) 486 { 487 NV_STATUS rmStatus = NV_OK; 488 NvU32 index; 489 OBJSYS *pSys = SYS_GET_INSTANCE(); 490 KernelVgpuMgr *pKernelVgpuMgr = SYS_GET_KERNEL_VGPUMGR(pSys); 491 RM_API *pRmApi = GPU_GET_PHYSICAL_RMAPI(pGpu); 492 VGPU_TYPE *pVgpuTypeInfo; 493 KERNEL_PHYS_GPU_INFO *pPgpuInfo; 494 NV2080_CTRL_VGPU_MGR_INTERNAL_PGPU_ADD_VGPU_TYPE_PARAMS *pAddVgpuTypeParams; 495 496 // TODO: Eliminate the heap allocation here 497 // NV2080_CTRL_VGPU_MGR_INTERNAL_PGPU_ADD_VGPU_TYPE_PARAMS has massive size 498 // because it has an embedded struct VGPU_TYPE instead of a pointer. 499 // FINN won't be able to figure out serialization for a pointer at this moment. 500 pAddVgpuTypeParams = portMemAllocNonPaged(sizeof(*pAddVgpuTypeParams)); 501 if (pAddVgpuTypeParams == NULL) 502 { 503 NV_PRINTF(LEVEL_ERROR, "Failed to alloc add vGPU type ctrl params.\n"); 504 return NV_ERR_NO_MEMORY; 505 } 506 portMemSet(pAddVgpuTypeParams, 0, sizeof(*pAddVgpuTypeParams)); 507 508 pAddVgpuTypeParams->discardVgpuTypes = discardVgpuTypes; 509 pAddVgpuTypeParams->vgpuInfoCount = 1; 510 pAddVgpuTypeParams->vgpuInfo[0] = *pVgpuInfo; 511 512 rmStatus = pRmApi->Control(pRmApi, pGpu->hInternalClient, pGpu->hInternalSubdevice, 513 NV2080_CTRL_CMD_VGPU_MGR_INTERNAL_PGPU_ADD_VGPU_TYPE, 514 pAddVgpuTypeParams, sizeof(*pAddVgpuTypeParams)); 515 516 portMemFree(pAddVgpuTypeParams); 517 518 if (rmStatus != NV_OK) 519 { 520 NV_PRINTF(LEVEL_ERROR, "Failed to create vGPU type on GSP.\n"); 521 return rmStatus; 522 } 523 524 if (kvgpumgrGetPgpuIndex(pKernelVgpuMgr, pGpu->gpuId, &index) != NV_OK) 525 { 526 return NV_ERR_OBJECT_NOT_FOUND; 527 } 528 529 pPgpuInfo = &(pKernelVgpuMgr->pgpuInfo[index]); 530 531 if (pPgpuInfo->numVgpuTypes == NVA081_MAX_VGPU_TYPES_PER_PGPU && !discardVgpuTypes) 532 { 533 return NV_ERR_NOT_SUPPORTED; 534 } 535 536 // TODO: This is a WAR. Need to do this change in VGPUD. 537 if (pPgpuInfo->fractionalMultiVgpu == 0 && pVgpuInfo->maxInstance != 1) 538 { 539 pVgpuInfo->multiVgpuSupported = 0; 540 } 541 542 rmStatus = kvgpumgrGetVgpuTypeInfo(pVgpuInfo->vgpuType, &pVgpuTypeInfo); 543 if (rmStatus == NV_ERR_OBJECT_NOT_FOUND) 544 { 545 rmStatus = _kvgpumgrCreateVgpuType(pVgpuInfo, &pVgpuTypeInfo); 546 if (rmStatus != NV_OK) 547 { 548 NV_PRINTF(LEVEL_ERROR, "Failed to create vGPU type.\n"); 549 return rmStatus; 550 } 551 } 552 else if (rmStatus != NV_OK) 553 { 554 NV_PRINTF(LEVEL_ERROR, "Failed to get vGPU type.\n"); 555 return rmStatus; 556 } 557 558 if (discardVgpuTypes) 559 { 560 pPgpuInfo->numVgpuTypes = 0; 561 } 562 563 if (pPgpuInfo->numVgpuTypes == 0) 564 { 565 pPgpuInfo->sriovEnabled = gpuIsSriovEnabled(pGpu); 566 } 567 568 pPgpuInfo->vgpuTypes[pPgpuInfo->numVgpuTypes] = pVgpuTypeInfo; 569 pPgpuInfo->numVgpuTypes++; 570 571 return NV_OK; 572 } 573 574 NV_STATUS 575 kvgpumgrAttachGpu(NvU32 gpuPciId) 576 { 577 NvU32 index; 578 OBJSYS *pSys = SYS_GET_INSTANCE(); 579 KernelVgpuMgr *pKernelVgpuMgr = SYS_GET_KERNEL_VGPUMGR(pSys); 580 KERNEL_PHYS_GPU_INFO *pPhysGpuInfo; 581 582 NV_PRINTF(LEVEL_INFO, "Enter function\n"); 583 584 NV_ASSERT_OR_RETURN((pKernelVgpuMgr != NULL), NV_ERR_NOT_SUPPORTED); 585 586 index = 0; 587 while ((index < pKernelVgpuMgr->pgpuCount) && 588 ((pKernelVgpuMgr->pgpuInfo[index].isAttached == NV_TRUE) || 589 (pKernelVgpuMgr->pgpuInfo[index].gpuPciId != gpuPciId))) 590 { 591 index++; 592 } 593 NV_ASSERT_OR_RETURN((index != NV_MAX_DEVICES), NV_ERR_INSUFFICIENT_RESOURCES); 594 595 pPhysGpuInfo = &(pKernelVgpuMgr->pgpuInfo[index]); 596 597 /* Probe call, RmInit is not done yet, so send pGpu as NULL */ 598 kvgpumgrSetVgpuType(NULL, pPhysGpuInfo, NVA081_CTRL_VGPU_CONFIG_INVALID_TYPE); 599 pPhysGpuInfo->numActiveVgpu = 0; 600 pPhysGpuInfo->isAttached = NV_TRUE; 601 pPhysGpuInfo->numCreatedVgpu = 0; 602 603 listInit(&(pKernelVgpuMgr->pgpuInfo[index].listVgpuConfigEventsHead), portMemAllocatorGetGlobalNonPaged()); 604 listInit(&(pKernelVgpuMgr->pgpuInfo[index].listHostVgpuDeviceHead), portMemAllocatorGetGlobalNonPaged()); 605 606 if (index == pKernelVgpuMgr->pgpuCount) 607 { 608 pPhysGpuInfo->gpuPciId = gpuPciId; 609 pPhysGpuInfo->numVgpuTypes = 0; 610 pPhysGpuInfo->vgpuConfigState = NVA081_CTRL_VGPU_CONFIG_STATE_UNINITIALIZED; 611 pKernelVgpuMgr->pgpuCount++; 612 } 613 614 return NV_OK; 615 } 616 617 NV_STATUS 618 kvgpumgrDetachGpu(NvU32 gpuPciId) 619 { 620 NvU32 i; 621 OBJSYS *pSys = SYS_GET_INSTANCE(); 622 KernelVgpuMgr *pKernelVgpuMgr = SYS_GET_KERNEL_VGPUMGR(pSys); 623 KERNEL_PHYS_GPU_INFO *pPhysGpuInfo; 624 625 NV_PRINTF(LEVEL_INFO, "Enter function\n"); 626 627 NV_ASSERT_OR_RETURN((pKernelVgpuMgr != NULL), NV_ERR_NOT_SUPPORTED); 628 629 if (kvgpumgrGetPgpuIndex(pKernelVgpuMgr, gpuPciId, &i) != NV_OK) 630 return NV_ERR_OBJECT_NOT_FOUND; 631 632 pPhysGpuInfo = &(pKernelVgpuMgr->pgpuInfo[i]); 633 634 pPhysGpuInfo->createdVfMask = 0; 635 pPhysGpuInfo->assignedSwizzIdMask = 0; 636 pPhysGpuInfo->isAttached = NV_FALSE; 637 638 listDestroy(&(pPhysGpuInfo->listHostVgpuDeviceHead)); 639 640 return NV_OK; 641 } 642 643 /* 644 * @brief Sets Guest(VM) ID for the requested hostvgpudevice 645 * 646 * @param pParams SET_GUEST_ID_PARAMS Pointer 647 * @param pKernelHostVgpuDevice Device for which Vm ID need to be set 648 * @param pGpu OBJGPU pointer 649 * 650 * @return NV_STATUS 651 */ 652 NV_STATUS 653 kvgpumgrRegisterGuestId(SET_GUEST_ID_PARAMS *pParams, 654 KERNEL_HOST_VGPU_DEVICE *pKernelHostVgpuDevice, OBJGPU *pGpu) 655 { 656 NV_STATUS rmStatus = NV_OK; 657 OBJSYS *pSys = SYS_GET_INSTANCE(); 658 KernelVgpuMgr *pKernelVgpuMgr = SYS_GET_KERNEL_VGPUMGR(pSys); 659 660 if (pParams->action == SET_GUEST_ID_ACTION_SET) 661 { 662 KERNEL_VGPU_GUEST *pVgpuGuest = NULL; 663 664 for (pVgpuGuest = listHead(&(pKernelVgpuMgr->listVgpuGuestHead)); 665 pVgpuGuest != NULL; 666 pVgpuGuest = listNext(&(pKernelVgpuMgr->listVgpuGuestHead), pVgpuGuest)) 667 { 668 if (pParams->vmIdType == pVgpuGuest->guestVmInfo.vmIdType) 669 { 670 if (pParams->vmIdType == VM_ID_DOMAIN_ID) 671 { 672 if (pParams->guestVmId.vmId == pVgpuGuest->guestVmInfo.guestVmId.vmId) 673 { 674 break; 675 } 676 } 677 else if (pParams->vmIdType == VM_ID_UUID) 678 { 679 if (!portMemCmp(pParams->guestVmId.vmUuid, 680 pVgpuGuest->guestVmInfo.guestVmId.vmUuid, 681 VM_UUID_SIZE)) 682 { 683 break; 684 } 685 } 686 else 687 return NV_ERR_INVALID_ARGUMENT; 688 } 689 } 690 691 if (pVgpuGuest == NULL) 692 { 693 pVgpuGuest = listAppendNew(&(pKernelVgpuMgr->listVgpuGuestHead)); 694 if (pVgpuGuest == NULL) 695 return NV_ERR_NO_MEMORY; 696 697 portMemSet(pVgpuGuest, 0, sizeof(KERNEL_VGPU_GUEST)); 698 } 699 700 NV_ASSERT_OR_RETURN(pVgpuGuest->numVgpuDevices != MAX_VGPU_DEVICES_PER_VM, 701 NV_ERR_INSUFFICIENT_RESOURCES); 702 703 pVgpuGuest->numVgpuDevices++; 704 705 pKernelHostVgpuDevice->vgpuGuest = pVgpuGuest; 706 707 pVgpuGuest->guestVmInfo.vmIdType = pParams->vmIdType; 708 709 if (pParams->vmIdType == VM_ID_DOMAIN_ID) 710 { 711 pVgpuGuest->guestVmInfo.guestVmId.vmId = pParams->guestVmId.vmId; 712 } 713 else if (pParams->vmIdType == VM_ID_UUID) 714 { 715 portMemCopy(pVgpuGuest->guestVmInfo.guestVmId.vmUuid, 716 VM_UUID_SIZE, 717 pParams->guestVmId.vmUuid, 718 VM_UUID_SIZE); 719 } 720 } 721 else if (pParams->action == SET_GUEST_ID_ACTION_UNSET) 722 { 723 KERNEL_VGPU_GUEST *pVgpuGuest = pKernelHostVgpuDevice->vgpuGuest; 724 725 if (pVgpuGuest) 726 { 727 pVgpuGuest->numVgpuDevices--; 728 if (pVgpuGuest->numVgpuDevices == 0) 729 { 730 listRemove(&(pKernelVgpuMgr->listVgpuGuestHead), pVgpuGuest); 731 } 732 pKernelHostVgpuDevice->vgpuGuest = NULL; 733 } 734 else 735 { 736 return NV_WARN_NULL_OBJECT; 737 } 738 } 739 else 740 { 741 return NV_ERR_INVALID_ARGUMENT; 742 } 743 744 return rmStatus; 745 } 746 747 static NV_STATUS 748 _kvgpumgrVgpuAllocGPUInstanceSubscription 749 ( 750 OBJGPU *pGpu, 751 NvU32 *phClient, 752 NvU32 *phDevice, 753 NvU32 swizzId 754 ) 755 { 756 NV_STATUS rmStatus; 757 NVC637_ALLOCATION_PARAMETERS nvC637AllocParams; 758 NvU32 hSubDevice; 759 NvU32 hGPUInstanceSubscription; 760 RM_API *pRmApi = rmapiGetInterface(RMAPI_GPU_LOCK_INTERNAL); 761 762 NV_ASSERT_OR_RETURN(phClient != NULL, NV_ERR_INVALID_ARGUMENT); 763 NV_ASSERT_OR_RETURN(phDevice != NULL, NV_ERR_INVALID_ARGUMENT); 764 765 NV_ASSERT_OK_OR_RETURN( 766 rmapiutilAllocClientAndDeviceHandles(pRmApi, pGpu, phClient, phDevice, &hSubDevice)); 767 768 // Allocate GPUInstanceSubscription handle 769 NV_ASSERT_OK_OR_GOTO( 770 rmStatus, 771 serverutilGenResourceHandle(*phClient, &hGPUInstanceSubscription), 772 cleanup); 773 portMemSet(&nvC637AllocParams, 0, sizeof(nvC637AllocParams)); 774 nvC637AllocParams.swizzId = swizzId; 775 776 // Allocate GPUInstanceSubscription object 777 NV_CHECK_OK_OR_GOTO( 778 rmStatus, 779 LEVEL_ERROR, 780 pRmApi->AllocWithHandle(pRmApi, 781 *phClient, 782 hSubDevice, 783 hGPUInstanceSubscription, 784 AMPERE_SMC_PARTITION_REF, 785 &nvC637AllocParams, 786 sizeof(nvC637AllocParams)), 787 cleanup); 788 789 return rmStatus; 790 791 cleanup: 792 pRmApi->Free(pRmApi, *phClient, *phClient); 793 return rmStatus; 794 } 795 796 NV_STATUS 797 kvgpumgrHeterogeneousGetChidOffset(NvU32 vgpuTypeId, NvU16 placementId, 798 NvU32 numChannels, NvU64 *pChidOffset) 799 { 800 VGPU_TYPE *pVgpuTypeInfo = NULL; 801 NV_STATUS status; 802 NvU32 i; 803 804 if ((status = kvgpumgrGetVgpuTypeInfo(vgpuTypeId, &pVgpuTypeInfo)) != NV_OK) 805 return status; 806 807 if ((placementId == NVA081_PLACEMENT_ID_INVALID)) 808 return NV_ERR_INVALID_ARGUMENT; 809 810 /* Channel count provided by plugin and calculated by RM should be same */ 811 if (numChannels != pVgpuTypeInfo->channelCount) 812 return NV_ERR_INVALID_STATE; 813 814 if (pVgpuTypeInfo->placementCount > MAX_VGPU_DEVICES_PER_PGPU) 815 return NV_ERR_INVALID_INDEX; 816 817 for (i = 0; i < pVgpuTypeInfo->placementCount; i++) 818 { 819 /* 820 * For the placementId of the vGPU instance, find the corresponding 821 * channel offset. supportedPlacementIds and supportedChidOffsets 822 * share the same array index for a give placement ID. 823 */ 824 if (placementId == pVgpuTypeInfo->supportedPlacementIds[i]) 825 { 826 *pChidOffset = pVgpuTypeInfo->supportedChidOffsets[i]; 827 return NV_OK; 828 } 829 } 830 831 return NV_ERR_OBJECT_NOT_FOUND; 832 } 833 834 835 NV_STATUS 836 kvgpumgrGuestRegister(OBJGPU *pGpu, 837 NvU32 gfid, 838 NvU32 vgpuType, 839 NvU32 vmPid, 840 VM_ID_TYPE vmIdType, 841 VM_ID guestVmId, 842 NvHandle hPluginFBAllocationClient, 843 NvU32 numChannels, 844 NvU32 numPluginChannels, 845 NvU32 swizzId, 846 NvU32 vgpuDeviceInstanceId, 847 NvBool bDisableDefaultSmcExecPartRestore, 848 NvU16 placementId, 849 KERNEL_HOST_VGPU_DEVICE **ppKernelHostVgpuDevice) 850 { 851 NV_STATUS rmStatus = NV_OK; 852 OBJSYS *pSys = SYS_GET_INSTANCE(); 853 KernelVgpuMgr *pKernelVgpuMgr = SYS_GET_KERNEL_VGPUMGR(pSys); 854 SET_GUEST_ID_PARAMS setGuestIDParams = {0}; 855 NvU32 i; 856 KERNEL_PHYS_GPU_INFO *pPhysGpuInfo; 857 KERNEL_HOST_VGPU_DEVICE *pKernelHostVgpuDevice = NULL; 858 NvBool bMIGInUse = IS_MIG_IN_USE(pGpu); 859 860 NvU32 j; 861 NvU32 vgpuTypeId = 0; 862 REQUEST_VGPU_INFO_NODE *pRequestVgpu = NULL; 863 864 NV_PRINTF(LEVEL_INFO, "Enter function\n"); 865 866 if (numPluginChannels > VGPU_MAX_PLUGIN_CHANNELS) 867 { 868 NV_PRINTF(LEVEL_ERROR, "failed, wrong number of plugin channels\n"); 869 return NV_ERR_INVALID_PARAMETER; 870 } 871 872 if (pGpu->getProperty(pGpu, PDB_PROP_GPU_IS_VIRTUALIZATION_MODE_HOST_VSGA)) 873 { 874 NV_PRINTF(LEVEL_ERROR, "GPU is previously set in vSGA mode!\n"); 875 return NV_ERR_INVALID_DEVICE; 876 } 877 878 if (gpuIsSriovEnabled(pGpu)) 879 { 880 GFID_ALLOC_STATUS gfidState; 881 NV_ASSERT_OK_OR_RETURN(gpuGetGfidState(pGpu, gfid, &gfidState)); 882 NV_ASSERT_OR_RETURN((gfidState == GFID_FREE), NV_ERR_INSUFFICIENT_RESOURCES); 883 } 884 else 885 { 886 // MIG is supported only with SRIOV. Legacy mode doesn't support MIG 887 NV_ASSERT_OR_RETURN(!bMIGInUse, NV_ERR_INVALID_STATE); 888 numPluginChannels = 0; 889 } 890 891 if (kvgpumgrGetPgpuIndex(pKernelVgpuMgr, pGpu->gpuId, &i) != NV_OK) 892 return NV_ERR_OBJECT_NOT_FOUND; 893 894 pPhysGpuInfo = &(pKernelVgpuMgr->pgpuInfo[i]); 895 896 // check if this vgpu type is allowed on physical gpu 897 for (j = 0; j < pPhysGpuInfo->numVgpuTypes; j++) 898 { 899 if (vgpuType == pPhysGpuInfo->vgpuTypes[j]->vgpuTypeId) 900 { 901 vgpuTypeId = j; 902 break; 903 } 904 } 905 906 if (j == pPhysGpuInfo->numVgpuTypes) 907 { 908 return NV_ERR_NOT_SUPPORTED; 909 } 910 911 // On KVM, store a link to the corresponding REQUEST_VGPU_INFO_NODE in 912 // KERNEL_HOST_VGPU_DEVICE and vice versa, so as to create a mapping between 913 // vGPU device and the corresponding mdev device. 914 if (osIsVgpuVfioPresent() == NV_OK) 915 { 916 for (pRequestVgpu = listHead(&pKernelVgpuMgr->listRequestVgpuHead); 917 pRequestVgpu != NULL; 918 pRequestVgpu = listNext(&pKernelVgpuMgr->listRequestVgpuHead, pRequestVgpu)) 919 { 920 if (pRequestVgpu->deviceState == NV_VGPU_DEV_OPENED) 921 break; 922 } 923 if (pRequestVgpu == NULL) 924 { 925 return NV_ERR_OBJECT_NOT_FOUND; 926 } 927 } 928 929 /* 930 * For MIG mode, vGPU type is already validated based on swizzid in 931 * NVA081_CTRL_CMD_VGPU_CONFIG_[GET_FREE|VALIDATE]_SWIZZID RmCtrl. 932 * For heterogeneous vGPU mode, vGPU type is already validated based on placement ID 933 * in NVA081_CTRL_CMD_VGPU_CONFIG_UPDATE_HETEROGENEOUS_INFO RmCtrl. 934 * Both the RmCtrls are done before allocating the A084 object. 935 */ 936 if (!IS_MIG_ENABLED(pGpu) && !pGpu->getProperty(pGpu, PDB_PROP_GPU_IS_VGPU_HETEROGENEOUS_MODE)) 937 { 938 rmStatus = _kvgpumgrCheckVgpuTypeActivatable(pGpu, pPhysGpuInfo, pPhysGpuInfo->vgpuTypes[vgpuTypeId]); 939 if (rmStatus != NV_OK) 940 return rmStatus; 941 942 rmStatus = kvgpumgrSetVgpuType(pGpu, pPhysGpuInfo, vgpuType); 943 if (rmStatus != NV_OK) 944 return rmStatus; 945 } 946 947 if (listCount(&(pPhysGpuInfo->listHostVgpuDeviceHead)) == MAX_VGPU_DEVICES_PER_PGPU) 948 { 949 rmStatus = NV_ERR_INSUFFICIENT_RESOURCES; 950 goto failed; 951 } 952 953 // Register guest vgpu device instance 954 pKernelHostVgpuDevice = listAppendNew(&(pPhysGpuInfo->listHostVgpuDeviceHead)); 955 if (pKernelHostVgpuDevice == NULL) 956 { 957 rmStatus = NV_ERR_NO_MEMORY; 958 goto failed; 959 } 960 961 portMemSet(pKernelHostVgpuDevice, 0, sizeof(KERNEL_HOST_VGPU_DEVICE)); 962 963 pKernelHostVgpuDevice->vgpuType = vgpuType; 964 965 setGuestIDParams.action = SET_GUEST_ID_ACTION_SET; 966 setGuestIDParams.vmPid = vmPid; 967 setGuestIDParams.vmIdType = vmIdType; 968 if (vmIdType == VM_ID_DOMAIN_ID) 969 { 970 setGuestIDParams.guestVmId.vmId = guestVmId.vmId; 971 } 972 else if (vmIdType == VM_ID_UUID) 973 { 974 portMemCopy(setGuestIDParams.guestVmId.vmUuid, 975 VM_UUID_SIZE, 976 guestVmId.vmUuid, 977 VM_UUID_SIZE); 978 } 979 if (NV_OK != (rmStatus = kvgpumgrRegisterGuestId(&setGuestIDParams, pKernelHostVgpuDevice, pGpu))) 980 { 981 goto failed; 982 } 983 984 pKernelHostVgpuDevice->gfid = gfid; 985 pKernelHostVgpuDevice->swizzId = swizzId; 986 pKernelHostVgpuDevice->numPluginChannels = numPluginChannels; 987 pKernelHostVgpuDevice->bDisableDefaultSmcExecPartRestore = bDisableDefaultSmcExecPartRestore; 988 pKernelHostVgpuDevice->placementId = placementId; 989 990 if (osIsVgpuVfioPresent() == NV_OK) 991 { 992 pKernelHostVgpuDevice->pRequestVgpuInfoNode = pRequestVgpu; 993 pRequestVgpu->pKernelHostVgpuDevice = pKernelHostVgpuDevice; 994 } 995 996 pKernelHostVgpuDevice->hPluginFBAllocationClient = hPluginFBAllocationClient; 997 pKernelHostVgpuDevice->vgpuDeviceGuestFbInfo.bValid = NV_FALSE; 998 pKernelHostVgpuDevice->vgpuDeviceGuestFbInfo.offset = 0; 999 pKernelHostVgpuDevice->vgpuDeviceGuestFbInfo.length = 0; 1000 pKernelHostVgpuDevice->bOfflinedPageInfoValid = NV_FALSE; 1001 1002 pPhysGpuInfo->numActiveVgpu++; 1003 1004 if (gpuIsSriovEnabled(pGpu)) 1005 { 1006 // Set GFID in use 1007 gpuSetGfidUsage(pGpu, gfid, NV_TRUE); 1008 } 1009 1010 // If MIG is enabled, then we need to set faultIds and per GPU instance VEID 1011 // offset in MMU_CFG registers. In MIG with memory partitioning, every 1012 // VM should be associated with a GPU instance, so set these params for 1013 // GPU instance engines 1014 // 1015 if (gpuIsSriovEnabled(pGpu) && bMIGInUse) 1016 { 1017 // 1018 // Alloc GPUInstanceSubscription object inside hostVgpuDeviceObject. This is 1019 // needed because hostVgpuDevice can be duped under any client and 1020 // will get freed after subdevice, so during hostVgpuDeviceDestruct 1021 // to get GPU instance reference, we need to keep the GPU instance alive 1022 // 1023 NV_ASSERT_OK_OR_GOTO(rmStatus, _kvgpumgrVgpuAllocGPUInstanceSubscription(pGpu, 1024 &pKernelHostVgpuDevice->hMigClient, 1025 &pKernelHostVgpuDevice->hMigDevice, 1026 swizzId), 1027 failed); 1028 } 1029 1030 if (IS_GSP_CLIENT(pGpu)) 1031 { 1032 KernelFifo *pKernelFifo = GPU_GET_KERNEL_FIFO(pGpu); 1033 ENGINE_INFO tmpEngineInfo; 1034 VGPU_TYPE *vgpuTypeInfo = NULL; 1035 Device *pMigDevice = NULL; 1036 1037 if (gpuIsSriovEnabled(pGpu) && bMIGInUse) 1038 { 1039 RsClient *pClient; 1040 1041 NV_ASSERT_OK_OR_GOTO(rmStatus, 1042 serverGetClientUnderLock(&g_resServ, pKernelHostVgpuDevice->hMigClient, &pClient), 1043 failed); 1044 1045 NV_ASSERT_OK_OR_GOTO(rmStatus, 1046 deviceGetByHandle(pClient, pKernelHostVgpuDevice->hMigDevice, &pMigDevice), 1047 failed); 1048 } 1049 1050 NV_ASSERT_OK_OR_GOTO(rmStatus, 1051 kvgpumgrGetVgpuTypeInfo(vgpuType, &vgpuTypeInfo), 1052 failed); 1053 1054 portMemSet(&tmpEngineInfo, 0, sizeof(ENGINE_INFO)); 1055 1056 NV_ASSERT_OK_OR_GOTO(rmStatus, 1057 kfifoGetHostDeviceInfoTable_HAL(pGpu, pKernelFifo, &tmpEngineInfo, pMigDevice), 1058 failed); 1059 1060 rmStatus = vgpuMgrReserveSystemChannelIDs(pGpu, 1061 vgpuTypeInfo, 1062 pKernelHostVgpuDevice->gfid, 1063 pKernelHostVgpuDevice->chidOffset, 1064 pKernelHostVgpuDevice->channelCount, 1065 pMigDevice, 1066 numChannels, 1067 pKernelHostVgpuDevice->placementId, 1068 tmpEngineInfo.engineInfoListSize, 1069 tmpEngineInfo.engineInfoList); 1070 1071 portMemFree(tmpEngineInfo.engineInfoList); 1072 tmpEngineInfo.engineInfoList = NULL; 1073 1074 if (rmStatus != NV_OK) 1075 { 1076 goto failed; 1077 } 1078 } 1079 1080 // Save/Restore default compute instance if not disabled during allocation 1081 if (gpuIsSriovEnabled(pGpu) && bMIGInUse && !pKernelHostVgpuDevice->bDisableDefaultSmcExecPartRestore) 1082 { 1083 KERNEL_MIG_GPU_INSTANCE *pKernelMIGGpuInstance; 1084 KernelMIGManager *pKernelMIGManager = GPU_GET_KERNEL_MIG_MANAGER(pGpu); 1085 1086 // Get GPU instance 1087 NV_ASSERT_OK_OR_GOTO(rmStatus, 1088 kmigmgrGetGPUInstanceInfo(pGpu, pKernelMIGManager, 1089 swizzId, &pKernelMIGGpuInstance), 1090 failed); 1091 // 1092 // Save any default compute instances as we may need to restore 1093 // them during destruct 1094 // 1095 NV_ASSERT_OK_OR_GOTO(rmStatus, 1096 kmigmgrSaveComputeInstances(pGpu, pKernelMIGManager, pKernelMIGGpuInstance, 1097 pKernelHostVgpuDevice->savedExecPartitions), 1098 failed); 1099 1100 // Determine if we have a VEID fragmentation between compute instances 1101 if (!kmigmgrIsPartitionVeidAllocationContiguous(pGpu, pKernelMIGManager, pKernelMIGGpuInstance)) 1102 { 1103 // delete all compute instances and recreate then again 1104 NV_ASSERT_OK_OR_GOTO(rmStatus, 1105 kvgpuMgrRestoreSmcExecPart(pGpu, 1106 pKernelHostVgpuDevice, 1107 pKernelMIGGpuInstance), 1108 failed); 1109 } 1110 } 1111 1112 *ppKernelHostVgpuDevice = pKernelHostVgpuDevice; 1113 1114 return rmStatus; 1115 1116 failed: 1117 // Unset gfid usage 1118 if (gpuIsSriovEnabled(pGpu)) 1119 gpuSetGfidUsage(pGpu, gfid, NV_FALSE); 1120 1121 if (pKernelHostVgpuDevice != NULL) 1122 { 1123 if (pKernelHostVgpuDevice->vgpuGuest != NULL) 1124 { 1125 setGuestIDParams.action = SET_GUEST_ID_ACTION_UNSET; 1126 kvgpumgrRegisterGuestId(&setGuestIDParams, pKernelHostVgpuDevice, pGpu); 1127 } 1128 listRemove(&(pPhysGpuInfo->listHostVgpuDeviceHead), pKernelHostVgpuDevice); 1129 } 1130 1131 if (osIsVgpuVfioPresent() != NV_OK && // not KVM 1132 swizzId != KMIGMGR_SWIZZID_INVALID) 1133 _kvgpumgrClearAssignedSwizzIdMask(pGpu, swizzId); 1134 1135 return rmStatus; 1136 } 1137 1138 NV_STATUS 1139 kvgpumgrGuestUnregister(OBJGPU *pGpu, KERNEL_HOST_VGPU_DEVICE *pKernelHostVgpuDevice) 1140 { 1141 NV_STATUS rmStatus = NV_OK; 1142 OBJSYS *pSys = SYS_GET_INSTANCE(); 1143 KernelVgpuMgr *pKernelVgpuMgr = SYS_GET_KERNEL_VGPUMGR(pSys); 1144 RM_API *pRmApi = rmapiGetInterface(RMAPI_GPU_LOCK_INTERNAL); 1145 KERNEL_PHYS_GPU_INFO *pPhysGpuInfo; 1146 NvU32 gfid = pKernelHostVgpuDevice->gfid; 1147 SET_GUEST_ID_PARAMS setGuestIDParams = {0}; 1148 NvU32 i; 1149 1150 NV_PRINTF(LEVEL_INFO, "Enter function\n"); 1151 1152 if (gpuIsSriovEnabled(pGpu)) 1153 { 1154 GFID_ALLOC_STATUS gfidState; 1155 1156 // Sanity check on GFID 1157 NV_ASSERT_OK_OR_GOTO(rmStatus, gpuGetGfidState(pGpu, gfid, &gfidState), done); 1158 1159 // Keep continuing in unregister path after sanity check 1160 if (gfidState == GFID_FREE) 1161 { 1162 NV_PRINTF(LEVEL_ERROR, "Request to unregister Invalid GFID\n"); 1163 rmStatus = NV_ERR_INVALID_STATE; 1164 goto done; 1165 } 1166 } 1167 1168 if (IS_MIG_IN_USE(pGpu) && !pKernelHostVgpuDevice->bDisableDefaultSmcExecPartRestore) 1169 { 1170 KernelMIGManager *pKernelMIGManager = GPU_GET_KERNEL_MIG_MANAGER(pGpu); 1171 KERNEL_MIG_GPU_INSTANCE *pKernelMIGGpuInstance; 1172 1173 NV_ASSERT_OK_OR_GOTO(rmStatus, kmigmgrGetGPUInstanceInfo(pGpu, pKernelMIGManager, 1174 pKernelHostVgpuDevice->swizzId, 1175 &pKernelMIGGpuInstance), 1176 done); 1177 1178 NV_ASSERT_OK_OR_GOTO(rmStatus, 1179 kvgpuMgrRestoreSmcExecPart(pGpu, 1180 pKernelHostVgpuDevice, 1181 pKernelMIGGpuInstance), 1182 done); 1183 1184 portMemSet(&pKernelHostVgpuDevice->savedExecPartitions, 0, 1185 sizeof(pKernelHostVgpuDevice->savedExecPartitions)); 1186 } 1187 1188 if (!gpuIsSriovEnabled(pGpu)) 1189 { 1190 portMemFree(pKernelHostVgpuDevice->pGuestFbSegment); 1191 pKernelHostVgpuDevice->pGuestFbSegment = NULL; 1192 } 1193 1194 if (pKernelHostVgpuDevice->hbmRegionList != NULL) 1195 { 1196 portMemFree(pKernelHostVgpuDevice->hbmRegionList); 1197 pKernelHostVgpuDevice->hbmRegionList = NULL; 1198 pKernelHostVgpuDevice->numValidHbmRegions = 0; 1199 } 1200 1201 if (gpuIsSriovEnabled(pGpu)) 1202 { 1203 if (IS_GSP_CLIENT(pGpu)) 1204 { 1205 KernelFifo *pKernelFifo = GPU_GET_KERNEL_FIFO(pGpu); 1206 ENGINE_INFO tmpEngineInfo; 1207 Device *pMigDevice = NULL; 1208 1209 portMemSet(&tmpEngineInfo, 0, sizeof(ENGINE_INFO)); 1210 1211 if (IS_MIG_IN_USE(pGpu)) 1212 { 1213 RsClient *pClient; 1214 1215 NV_ASSERT_OK_OR_GOTO(rmStatus, 1216 serverGetClientUnderLock(&g_resServ, pKernelHostVgpuDevice->hMigClient, &pClient), 1217 free_fifo_chids_exit); 1218 1219 NV_ASSERT_OK_OR_GOTO(rmStatus, 1220 deviceGetByHandle(pClient, pKernelHostVgpuDevice->hMigDevice, &pMigDevice), 1221 free_fifo_chids_exit); 1222 } 1223 1224 NV_ASSERT_OK_OR_GOTO(rmStatus, 1225 kfifoGetHostDeviceInfoTable_HAL(pGpu, pKernelFifo, &tmpEngineInfo, pMigDevice), 1226 free_fifo_chids_exit); 1227 1228 vgpuMgrFreeSystemChannelIDs(pGpu, 1229 pKernelHostVgpuDevice->gfid, 1230 pKernelHostVgpuDevice->chidOffset, 1231 pKernelHostVgpuDevice->channelCount, 1232 pMigDevice, 1233 tmpEngineInfo.engineInfoListSize, 1234 tmpEngineInfo.engineInfoList); 1235 1236 free_fifo_chids_exit: 1237 portMemFree(tmpEngineInfo.engineInfoList); 1238 tmpEngineInfo.engineInfoList = NULL; 1239 } 1240 1241 // Unset GFID usage 1242 gpuSetGfidUsage(pGpu, gfid, NV_FALSE); 1243 } 1244 1245 done: 1246 if (IS_MIG_IN_USE(pGpu)) 1247 { 1248 pRmApi->Free(pRmApi, pKernelHostVgpuDevice->hMigClient, pKernelHostVgpuDevice->hMigClient); 1249 pKernelHostVgpuDevice->hMigClient = NV01_NULL_OBJECT; 1250 pKernelHostVgpuDevice->hMigDevice = NV01_NULL_OBJECT; 1251 } 1252 1253 if (kvgpumgrGetPgpuIndex(pKernelVgpuMgr, pGpu->gpuId, &i) != NV_OK) 1254 { 1255 return NV_ERR_OBJECT_NOT_FOUND; 1256 } 1257 1258 // Unset the guest id for host vGPU device 1259 setGuestIDParams.action = SET_GUEST_ID_ACTION_UNSET; 1260 if (NV_OK != (rmStatus = kvgpumgrRegisterGuestId(&setGuestIDParams, 1261 pKernelHostVgpuDevice, 1262 pGpu))) 1263 { 1264 // In case of Hyper-V, On VM reboot KERNEL_HOST_VGPU_DEVICE is not destroyed. 1265 // As guest id is unset during VM reboot by plugin explicitly. So we 1266 // will receive NV_WARN_NULL_OBJECT here and we need to ignore it. 1267 // 1268 // In case, plugin doesn't get a chance to unset the guest id e.g. in case 1269 // of crash or Force shutdown/Turn off then we need to get it unset here. 1270 if (hypervisorIsType(OS_HYPERVISOR_HYPERV) && rmStatus == NV_WARN_NULL_OBJECT) 1271 { 1272 rmStatus = NV_OK; 1273 } 1274 else 1275 { 1276 return rmStatus; 1277 } 1278 } 1279 1280 pPhysGpuInfo = &(pKernelVgpuMgr->pgpuInfo[i]); 1281 1282 NV_ASSERT_OR_RETURN((pPhysGpuInfo != NULL), NV_ERR_INVALID_ARGUMENT); 1283 1284 pPhysGpuInfo->numActiveVgpu--; 1285 1286 if (pPhysGpuInfo->numActiveVgpu == 0 && pPhysGpuInfo->numCreatedVgpu == 0) 1287 { 1288 kvgpumgrSetVgpuType(pGpu, pPhysGpuInfo, NVA081_CTRL_VGPU_CONFIG_INVALID_TYPE); 1289 } 1290 1291 if (pKernelHostVgpuDevice->pRequestVgpuInfoNode != NULL) 1292 { 1293 pKernelHostVgpuDevice->pRequestVgpuInfoNode->pKernelHostVgpuDevice = NULL; 1294 } 1295 1296 if (osIsVgpuVfioPresent() != NV_OK) // Not KVM 1297 { 1298 if (pKernelHostVgpuDevice->swizzId != KMIGMGR_SWIZZID_INVALID) 1299 rmStatus = _kvgpumgrClearAssignedSwizzIdMask(pGpu, pKernelHostVgpuDevice->swizzId); 1300 } 1301 1302 if (pKernelHostVgpuDevice->placementId != NVA081_PLACEMENT_ID_INVALID) 1303 _kvgpumgrUpdateCreatablePlacementIds(pGpu, pKernelHostVgpuDevice->placementId, 1304 pKernelHostVgpuDevice->vgpuType, NV_FALSE); 1305 1306 listRemove(&(pPhysGpuInfo->listHostVgpuDeviceHead), pKernelHostVgpuDevice); 1307 1308 return rmStatus; 1309 } 1310 1311 // 1312 // Helper function to check if pGPU is live migration capable. 1313 // 1314 NvBool 1315 kvgpumgrCheckPgpuMigrationSupport(OBJGPU *pGpu) 1316 { 1317 RM_API *pRmApi = GPU_GET_PHYSICAL_RMAPI(pGpu); 1318 NV2080_CTRL_VGPU_MGR_INTERNAL_GET_PGPU_MIGRATION_SUPPORT_PARAMS params = {0}; 1319 NV_STATUS status; 1320 1321 NV_CHECK_OK_OR_ELSE(status, 1322 LEVEL_ERROR, 1323 pRmApi->Control(pRmApi, pGpu->hInternalClient, pGpu->hInternalSubdevice, 1324 NV2080_CTRL_CMD_VGPU_MGR_INTERNAL_GET_PGPU_MIGRATION_SUPPORT, 1325 ¶ms, sizeof(params)), 1326 return NV_FALSE); 1327 1328 return params.bIsMigrationSupported; 1329 } 1330 1331 // 1332 // Function to convert a NvU32 value to a ascii-encoded string. 1333 // The value will be padded with 0 to use up the totalWidth. The value 1334 // requiring space more that totalWidth will be truncated. 1335 // 1336 static NvU32 1337 NvU32ToAsciiStr(NvU32 uval, NvU32 totalWidth, NvU8 *dest, NvBool invalid) 1338 { 1339 NvU32 digitCount = 0; 1340 NvU8 nibble; 1341 1342 if (totalWidth == 0) 1343 return (totalWidth); 1344 1345 // Move the pointer to the end 1346 dest += (totalWidth - 1); 1347 1348 // Start copying the data from the end in the reverse order 1349 while (digitCount < totalWidth) 1350 { 1351 digitCount++; 1352 if (invalid == NV_TRUE) 1353 { 1354 *dest-- = 'X'; 1355 continue; 1356 } 1357 1358 nibble = uval & 0xF; 1359 *dest-- = (nibble <= 9) ? (nibble + '0') : (nibble - 10 + 'A'); 1360 uval = uval >> 4; 1361 } 1362 1363 return (totalWidth); 1364 } 1365 1366 NvU32 kvgpumgrGetPgpuDevIdEncoding(OBJGPU *pGpu, NvU8 *pgpuString, 1367 NvU32 strSize) 1368 { 1369 NvU32 chipID = DRF_VAL(_PCI, _DEVID, _DEVICE, pGpu->idInfo.PCIDeviceID); 1370 NvU32 subID = DRF_VAL(_PCI, _DEVID, _DEVICE, pGpu->idInfo.PCISubDeviceID); 1371 1372 _get_chip_id_for_alias_pgpu(&chipID, &subID); 1373 1374 if ((strSize < MAX_NVU32_TO_CONVERTED_STR_LEN) 1375 || (pgpuString == NULL)) 1376 { 1377 return NV_U32_MAX; 1378 } 1379 1380 // The encoding of the Dev ID is the value converted to string 1381 return (NvU32ToAsciiStr(chipID, DEVID_ENCODED_VALUE_SIZE, pgpuString, NV_FALSE)); 1382 } 1383 1384 NvU32 kvgpumgrGetPgpuSubdevIdEncoding(OBJGPU *pGpu, NvU8 *pgpuString, 1385 NvU32 strSize) 1386 { 1387 NvU32 chipID = DRF_VAL(_PCI, _DEVID, _DEVICE, pGpu->idInfo.PCIDeviceID); 1388 NvU32 subID = DRF_VAL(_PCI, _DEVID, _DEVICE, pGpu->idInfo.PCISubDeviceID); 1389 NvU32 bytes = 0; 1390 1391 _get_chip_id_for_alias_pgpu(&chipID, &subID); 1392 1393 if ((strSize < MAX_NVU32_TO_CONVERTED_STR_LEN) 1394 || (pgpuString == NULL)) 1395 { 1396 return NV_U32_MAX; 1397 } 1398 1399 // The encoding of the subdevice ID is its value converted to string 1400 bytes = NvU32ToAsciiStr(subID, SUBDEVID_ENCODED_VALUE_SIZE, 1401 pgpuString, NV_FALSE); 1402 return bytes; 1403 } 1404 1405 NvU32 kvgpumgrGetPgpuFSEncoding(OBJGPU *pGpu, NvU8 *pgpuString, 1406 NvU32 strSize) 1407 { 1408 RM_API *pRmApi = GPU_GET_PHYSICAL_RMAPI(pGpu); 1409 NV2080_CTRL_VGPU_MGR_INTERNAL_GET_PGPU_FS_ENCODING_PARAMS params = {0}; 1410 NV_STATUS status; 1411 1412 params.pgpuStringSize = strSize; 1413 1414 NV_CHECK_OK_OR_ELSE(status, 1415 LEVEL_ERROR, 1416 pRmApi->Control(pRmApi, pGpu->hInternalClient, pGpu->hInternalSubdevice, 1417 NV2080_CTRL_CMD_VGPU_MGR_INTERNAL_GET_PGPU_FS_ENCODING, 1418 ¶ms, sizeof(params)), 1419 return NV_U32_MAX); 1420 1421 portMemCopy(pgpuString, strSize, params.pgpuString, params.pgpuStringSize); 1422 1423 return params.pgpuStringSize; 1424 } 1425 1426 NvU64 1427 kvgpumgrGetEccAndPrReservedFb(OBJGPU *pGpu) 1428 { 1429 Heap *pHeap = GPU_GET_HEAP(pGpu); 1430 const MEMORY_SYSTEM_STATIC_CONFIG *pMemorySystemConfig = 1431 kmemsysGetStaticConfig(pGpu, GPU_GET_KERNEL_MEMORY_SYSTEM(pGpu)); 1432 NvU64 eccReservedFb = 0, pageRetirementReservedFb = 0, usableSizeFb; 1433 1434 // 1435 // pageRetirementReservedFb is needed only in case of legacy, to account 1436 // for the pagepool used during page stitching 1437 // 1438 if (!gpuIsSriovEnabled(pGpu)) 1439 { 1440 if (pGpu->getProperty(pGpu, PDB_PROP_GPU_ALLOW_PAGE_RETIREMENT)) 1441 { 1442 if (IsPASCALorBetter(pGpu)) 1443 { 1444 pageRetirementReservedFb = NV2080_CTRL_FB_OFFLINED_PAGES_MAX_PAGES * RM_PAGE_SIZE_HUGE; 1445 } 1446 else 1447 { 1448 pageRetirementReservedFb = NV2080_CTRL_FB_OFFLINED_PAGES_MAX_PAGES * RM_PAGE_SIZE_64K; 1449 } 1450 } 1451 } 1452 1453 if (pMemorySystemConfig->bEnabledEccFBPA) 1454 { 1455 if ((pMemorySystemConfig->ramType != NV2080_CTRL_FB_INFO_RAM_TYPE_HBM1) && 1456 (pMemorySystemConfig->ramType != NV2080_CTRL_FB_INFO_RAM_TYPE_HBM2) && 1457 (pMemorySystemConfig->ramType != NV2080_CTRL_FB_INFO_RAM_TYPE_HBM3)) 1458 { 1459 heapGetUsableSize(pHeap, &usableSizeFb); 1460 // 1461 // FB and ECC checksum calculation 1462 // eccReservedFb = totalFBEccOff / 16 1463 // i.e. totalFbEccOff = eccReservedFb * 16 1464 // 1465 // totalFbEccOff = totalFbEccOn + eccReservedFb 1466 // eccReservedFb * 16 = totalFbEccOn + eccReservedFb 1467 // eccReservedFb * 15 = totalFbEccOn 1468 // eccReservedFb = totalFbEccOn / 15 (totalFbEccOn is same as usableSizeFb) 1469 // 1470 eccReservedFb = usableSizeFb / 15; 1471 } 1472 } 1473 1474 return pageRetirementReservedFb + eccReservedFb; 1475 } 1476 1477 // 1478 // A 32-bit variable is used to consolidate various GPU capabilities like 1479 // ECC, SRIOV etc. The function sets the capabilities in the variable and 1480 // converted to an ascii-encoded format. 1481 // 1482 NvU32 kvgpumgrGetPgpuCapEncoding(OBJGPU *pGpu, NvU8 *pgpuString, NvU32 strSize) 1483 { 1484 RM_API *pRmApi = GPU_GET_PHYSICAL_RMAPI(pGpu); 1485 NvU32 pgpuCap = 0; 1486 1487 if ((strSize < MAX_NVU32_TO_CONVERTED_STR_LEN) || (pgpuString == NULL)) 1488 { 1489 return NV_U32_MAX; 1490 } 1491 1492 { 1493 NV2080_CTRL_GPU_QUERY_ECC_STATUS_PARAMS eccStatus = {0}; 1494 1495 if (pRmApi->Control(pRmApi, 1496 pGpu->hInternalClient, 1497 pGpu->hInternalSubdevice, 1498 NV2080_CTRL_CMD_GPU_QUERY_ECC_STATUS, 1499 &eccStatus, sizeof(eccStatus)) == NV_OK) 1500 { 1501 NvU32 i; 1502 for (i = 0; i < NV2080_CTRL_GPU_ECC_UNIT_COUNT; i++) 1503 { 1504 if (eccStatus.units[i].enabled) 1505 { 1506 pgpuCap |= PGPU_CAP_ECC_ON; 1507 break; 1508 } 1509 } 1510 } 1511 } 1512 1513 { 1514 NV0080_CTRL_GPU_GET_SRIOV_CAPS_PARAMS sriovCaps = {0}; 1515 1516 if (gpuGetSriovCaps_HAL(pGpu, &sriovCaps) == NV_OK) 1517 { 1518 if (sriovCaps.bSriovEnabled) 1519 pgpuCap |= PGPU_CAP_SRIOV_ON; 1520 } 1521 } 1522 1523 return NvU32ToAsciiStr(pgpuCap, PGPU_CAP_ENCODED_VALUE_SIZE, 1524 pgpuString, NV_FALSE); 1525 } 1526 1527 /* 1528 * Get the user provide vGPU version range 1529 */ 1530 NV_STATUS 1531 kvgpumgrGetHostVgpuVersion(NvU32 *user_min_supported_version, 1532 NvU32 *user_max_supported_version) 1533 { 1534 OBJSYS *pSys = SYS_GET_INSTANCE(); 1535 KernelVgpuMgr *pKernelVgpuMgr = SYS_GET_KERNEL_VGPUMGR(pSys); 1536 1537 *user_min_supported_version 1538 = pKernelVgpuMgr->user_min_supported_version; 1539 *user_max_supported_version 1540 = pKernelVgpuMgr->user_max_supported_version; 1541 return NV_OK; 1542 } 1543 1544 /* 1545 * Set the user provide vGPU version range 1546 */ 1547 NV_STATUS 1548 kvgpumgrSetHostVgpuVersion(NvU32 user_min_supported_version, 1549 NvU32 user_max_supported_version) 1550 { 1551 OBJSYS *pSys = SYS_GET_INSTANCE(); 1552 KernelVgpuMgr *pKernelVgpuMgr = SYS_GET_KERNEL_VGPUMGR(pSys); 1553 NvU32 host_min_supported_version 1554 = GRIDSW_VERSION_EXTERNAL(NV_VGPU_MIN_SUPPORTED_GRIDSW_VERSION_EXTERNAL_MAJOR, 1555 NV_VGPU_MIN_SUPPORTED_GRIDSW_VERSION_EXTERNAL_MINOR); 1556 NvU32 host_max_supported_version 1557 = GRIDSW_VERSION_EXTERNAL(NV_VGPU_MAX_SUPPORTED_GRIDSW_VERSION_EXTERNAL_MAJOR, 1558 NV_VGPU_MAX_SUPPORTED_GRIDSW_VERSION_EXTERNAL_MINOR); 1559 1560 /* Sanity check */ 1561 if (user_min_supported_version > user_max_supported_version) { 1562 NV_PRINTF(LEVEL_ERROR, 1563 "Maximum vGPU version (0x%x) being set is less than minimum version (0x%x)\n", 1564 user_max_supported_version, user_min_supported_version); 1565 return NV_ERR_INVALID_ARGUMENT; 1566 } 1567 1568 /* Sanity check: Fail in case the range being set by admin is a subset 1569 * of the range supported by the host driver 1570 */ 1571 if ((user_min_supported_version < host_min_supported_version) 1572 || (user_max_supported_version > host_max_supported_version)) { 1573 1574 NV_PRINTF(LEVEL_ERROR, 1575 "vGPU version range being set (0x%x, 0x%x) is outside the range supported by host (0x%x, 0x%x)\n", 1576 user_min_supported_version, user_max_supported_version, 1577 host_min_supported_version, host_max_supported_version); 1578 1579 return NV_ERR_INVALID_ARGUMENT; 1580 } 1581 1582 NV_PRINTF(LEVEL_INFO, 1583 "vGPU version range enforced by user: (0x%x, 0x%x)\n", 1584 user_min_supported_version, user_max_supported_version); 1585 1586 /* Save the information of the user specified range in the host */ 1587 pKernelVgpuMgr->user_min_supported_version 1588 = user_min_supported_version; 1589 pKernelVgpuMgr->user_max_supported_version 1590 = user_max_supported_version; 1591 1592 return NV_OK; 1593 } 1594 1595 /* 1596 * Function to set swizzId is assigned to a vGPU device. 1597 */ 1598 static NV_STATUS 1599 _kvgpumgrSetAssignedSwizzIdMask(OBJGPU *pGpu, 1600 NvU32 swizzId) 1601 { 1602 OBJSYS *pSys = SYS_GET_INSTANCE(); 1603 KernelVgpuMgr *pKernelVgpuMgr = SYS_GET_KERNEL_VGPUMGR(pSys); 1604 KERNEL_PHYS_GPU_INFO *pPhysGpuInfo; 1605 NvU32 i; 1606 NvU64 mask; 1607 1608 if (swizzId >= KMIGMGR_MAX_GPU_SWIZZID) 1609 { 1610 return NV_ERR_INVALID_ARGUMENT; 1611 } 1612 1613 if (kvgpumgrGetPgpuIndex(pKernelVgpuMgr, pGpu->gpuId, &i) != NV_OK) 1614 { 1615 return NV_ERR_OBJECT_NOT_FOUND; 1616 } 1617 1618 pPhysGpuInfo = &(pKernelVgpuMgr->pgpuInfo[i]); 1619 NV_ASSERT_OR_RETURN((pPhysGpuInfo != NULL), NV_ERR_INVALID_ARGUMENT); 1620 1621 /* Validate that same ID is not already set and then set the ID */ 1622 mask = NVBIT64(swizzId); 1623 1624 if (mask & pPhysGpuInfo->assignedSwizzIdMask) 1625 { 1626 NV_PRINTF(LEVEL_ERROR, "SwizzID - %d already in use\n", swizzId); 1627 DBG_BREAKPOINT(); 1628 return NV_ERR_STATE_IN_USE; 1629 } 1630 1631 pPhysGpuInfo->assignedSwizzIdMask |= mask; 1632 1633 return NV_OK; 1634 } 1635 1636 /*! 1637 * Function to mark swizzId is free to be used by other vGPU devices. 1638 */ 1639 static NV_STATUS 1640 _kvgpumgrClearAssignedSwizzIdMask(OBJGPU *pGpu, 1641 NvU32 swizzId) 1642 { 1643 OBJSYS *pSys = SYS_GET_INSTANCE(); 1644 KernelVgpuMgr *pKernelVgpuMgr = SYS_GET_KERNEL_VGPUMGR(pSys); 1645 KERNEL_PHYS_GPU_INFO *pPhysGpuInfo; 1646 NvU32 i; 1647 NvU64 mask; 1648 1649 if (swizzId >= KMIGMGR_MAX_GPU_SWIZZID) 1650 { 1651 return NV_ERR_INVALID_ARGUMENT; 1652 } 1653 1654 if (kvgpumgrGetPgpuIndex(pKernelVgpuMgr, pGpu->gpuId, &i) != NV_OK) 1655 { 1656 return NV_ERR_OBJECT_NOT_FOUND; 1657 } 1658 1659 pPhysGpuInfo = &(pKernelVgpuMgr->pgpuInfo[i]); 1660 NV_ASSERT_OR_RETURN((pPhysGpuInfo != NULL), NV_ERR_INVALID_ARGUMENT); 1661 1662 /* Validate that same ID is not already marked as free and then set the ID */ 1663 mask = NVBIT64(swizzId); 1664 1665 if (!(mask & pPhysGpuInfo->assignedSwizzIdMask)) 1666 { 1667 NV_PRINTF(LEVEL_ERROR, "SwizzID - %d not in use\n", swizzId); 1668 DBG_BREAKPOINT(); 1669 return NV_ERR_INVALID_STATE; 1670 } 1671 1672 pPhysGpuInfo->assignedSwizzIdMask &= ~mask; 1673 1674 return NV_OK; 1675 } 1676 1677 NV_STATUS 1678 kvgpumgrGetSwizzId(OBJGPU *pGpu, 1679 KERNEL_PHYS_GPU_INFO *pPhysGpuInfo, 1680 NvU32 partitionFlag, 1681 NvU32 *swizzId) 1682 { 1683 KernelMIGManager *pKernelMIGManager = GPU_GET_KERNEL_MIG_MANAGER(pGpu); 1684 NvU64 swizzIdInUseMask = 0; 1685 NvU32 id; 1686 NV_STATUS rmStatus = NV_OK; 1687 1688 swizzIdInUseMask = kmigmgrGetSwizzIdInUseMask(pGpu, pKernelMIGManager); 1689 1690 *swizzId = KMIGMGR_SWIZZID_INVALID; 1691 1692 // Determine valid swizzids not assigned to any vGPU device. 1693 FOR_EACH_INDEX_IN_MASK(64, id, swizzIdInUseMask) 1694 { 1695 KERNEL_MIG_GPU_INSTANCE *pKernelMIGGpuInstance; 1696 NvU64 mask = 0; 1697 1698 rmStatus = kmigmgrGetGPUInstanceInfo(pGpu, pKernelMIGManager, id, &pKernelMIGGpuInstance); 1699 if (rmStatus != NV_OK) 1700 { 1701 // Didn't find requested GPU instance 1702 NV_PRINTF(LEVEL_ERROR, "No valid GPU instance with SwizzId - %d found\n", id); 1703 return rmStatus; 1704 } 1705 1706 mask = NVBIT64(id); 1707 1708 if (pKernelMIGGpuInstance->partitionFlag == partitionFlag) 1709 { 1710 // Validate that same ID is not already set and then set the ID 1711 if (!(mask & pPhysGpuInfo->assignedSwizzIdMask)) 1712 { 1713 NV_ASSERT_OK_OR_RETURN(_kvgpumgrSetAssignedSwizzIdMask(pGpu, pKernelMIGGpuInstance->swizzId)); 1714 *swizzId = pKernelMIGGpuInstance->swizzId; 1715 break; 1716 } 1717 } 1718 } 1719 FOR_EACH_INDEX_IN_MASK_END; 1720 1721 if (*swizzId == KMIGMGR_SWIZZID_INVALID) 1722 { 1723 return NV_ERR_INVALID_STATE; 1724 } 1725 1726 return NV_OK; 1727 } 1728 1729 NV_STATUS 1730 kvgpumgrValidateSwizzId(OBJGPU *pGpu, 1731 NvU32 vgpuTypeId, 1732 NvU32 swizzId) 1733 { 1734 KernelMIGManager *pKernelMIGManager = GPU_GET_KERNEL_MIG_MANAGER(pGpu); 1735 NvU32 partitionFlag = PARTITIONID_INVALID; 1736 NV_STATUS rmStatus = NV_OK; 1737 KERNEL_MIG_GPU_INSTANCE *pKernelMIGGpuInstance; 1738 1739 // Check if swizzId is valid. 1740 if (!kmigmgrIsSwizzIdInUse(pGpu, pKernelMIGManager, swizzId)) 1741 { 1742 return NV_ERR_INVALID_ARGUMENT; 1743 } 1744 1745 rmStatus = kmigmgrGetGPUInstanceInfo(pGpu, pKernelMIGManager, swizzId, &pKernelMIGGpuInstance); 1746 if (rmStatus != NV_OK) 1747 { 1748 // Didn't find requested GPU instance 1749 NV_PRINTF(LEVEL_ERROR, "No valid GPU instance with SwizzId - %d found\n", swizzId); 1750 return rmStatus; 1751 } 1752 1753 NV_ASSERT_OK_OR_RETURN( 1754 kvgpumgrGetPartitionFlag(vgpuTypeId, &partitionFlag)); 1755 1756 // Check if swizzId is valid for vGPU type. 1757 if (pKernelMIGGpuInstance->partitionFlag == partitionFlag) 1758 { 1759 NV_ASSERT_OK_OR_RETURN(_kvgpumgrSetAssignedSwizzIdMask(pGpu, swizzId)); 1760 return NV_OK; 1761 } 1762 1763 return NV_ERR_INVALID_STATE; 1764 } 1765 1766 NV_STATUS 1767 kvgpumgrGetPartitionFlag(NvU32 vgpuTypeId, NvU32 *partitionFlag) 1768 { 1769 NvU32 i; 1770 1771 *partitionFlag = PARTITIONID_INVALID; 1772 1773 for (i = 0; i < NV_ARRAY_ELEMENTS(vgpuSmcTypeIdMappings); i++) 1774 { 1775 if (vgpuSmcTypeIdMappings[i].vgpuTypeId == vgpuTypeId) 1776 { 1777 *partitionFlag = vgpuSmcTypeIdMappings[i].partitionFlag; 1778 return NV_OK; 1779 } 1780 } 1781 1782 NV_PRINTF(LEVEL_ERROR, "Invalid SMC vGpu TypeId: 0x%x\n", vgpuTypeId); 1783 return NV_ERR_INVALID_ARGUMENT; 1784 } 1785 1786 static NV_STATUS 1787 _kvgpumgrGetVgpuTypeIdFromPartitionFlag(NvU32 devId, NvU32 partitionFlag, NvU32 *vgpuTypeId) 1788 { 1789 NvU32 i; 1790 1791 *vgpuTypeId = NVA081_CTRL_VGPU_CONFIG_INVALID_TYPE; 1792 1793 for (i = 0; i < NV_ARRAY_ELEMENTS(vgpuSmcTypeIdMappings); i++) 1794 { 1795 // Currently vgpuTypeId to partitionFlag mapping is 1 to 1. 1796 // In future, we might potentially hit issue if multiple 1797 // type-ids map to the same partition flags 1798 if ((vgpuSmcTypeIdMappings[i].devId == devId) && 1799 (vgpuSmcTypeIdMappings[i].partitionFlag == partitionFlag)) 1800 { 1801 *vgpuTypeId = vgpuSmcTypeIdMappings[i].vgpuTypeId; 1802 return NV_OK; 1803 } 1804 } 1805 1806 return NV_ERR_OBJECT_NOT_FOUND; 1807 } 1808 1809 /* 1810 * Add or remove VF info to pgpuInfo of its PF 1811 * @param[in] gpuPciId PCI ID of target PF 1812 * @param[in] cmd 1813 * 0/VGPU_CMD_PROCESS_VF_INFO.NV_VGPU_SAVE_VF_INFO = Add VF info to VF list of target PF 1814 * 1/VGPU_CMD_PROCESS_VF_INFO.NV_VGPU_REMOVE_VF_INFO = Remove VF info from VF list of target PF 1815 * @param[in] domain Domain of VF to be stored 1816 * @param[in] bus Bus no. of VF to be stored 1817 * @param[in] slot Slot no. of VF to be stored 1818 * @param[in] function Function of VF to be stored 1819 * @param[in] isMdevAttached Flag to indicate if VF is registered with mdev 1820 * @param[out]vfPciInfo Array of PCI information of VFs 1821 */ 1822 NV_STATUS 1823 kvgpumgrProcessVfInfo(NvU32 gpuPciId, NvU8 cmd, NvU32 domain, NvU32 bus, NvU32 slot, NvU32 function, NvBool isMdevAttached, vgpu_vf_pci_info *vfPciInfo) 1824 { 1825 NvU32 i; 1826 OBJSYS *pSys = SYS_GET_INSTANCE(); 1827 KernelVgpuMgr *pKernelVgpuMgr = SYS_GET_KERNEL_VGPUMGR(pSys); 1828 NvU32 pgpuIndex; 1829 NV_STATUS status = NV_OK; 1830 KERNEL_PHYS_GPU_INFO *pPhysGpuInfo; 1831 vgpu_vf_pci_info *pVfInfo = NULL; 1832 1833 if ((status = kvgpumgrGetPgpuIndex(pKernelVgpuMgr, gpuPciId, &pgpuIndex)) != NV_OK) 1834 return status; 1835 1836 pPhysGpuInfo = &(pKernelVgpuMgr->pgpuInfo[pgpuIndex]); 1837 1838 if (cmd == NV_VGPU_SAVE_VF_INFO) 1839 { 1840 /* Find existing entry for VF and set flags if found. */ 1841 for (i = 0; i < MAX_VF_COUNT_PER_GPU; i++) 1842 { 1843 pVfInfo = &pPhysGpuInfo->vfPciInfo[i]; 1844 1845 if ((domain == pVfInfo->domain) && 1846 (bus == pVfInfo->bus) && 1847 (slot == pVfInfo->slot) && 1848 (function == pVfInfo->function)) 1849 { 1850 pVfInfo->isNvidiaAttached = NV_TRUE; 1851 pVfInfo->isMdevAttached = isMdevAttached; 1852 break; 1853 } 1854 } 1855 1856 /* 1857 * If entry doesn't already exist, populate an empty slot and complain 1858 * if there isn't one. 1859 */ 1860 if (i == MAX_VF_COUNT_PER_GPU) 1861 { 1862 for (i = 0; i < MAX_VF_COUNT_PER_GPU; i++) 1863 { 1864 pVfInfo = &pPhysGpuInfo->vfPciInfo[i]; 1865 if ((!pVfInfo->isNvidiaAttached)) 1866 { 1867 pVfInfo->domain = domain; 1868 pVfInfo->bus = bus; 1869 pVfInfo->slot = slot; 1870 pVfInfo->function = function; 1871 1872 pVfInfo->isNvidiaAttached = NV_TRUE; 1873 pVfInfo->isMdevAttached = isMdevAttached; 1874 break; 1875 } 1876 } 1877 1878 if (i == MAX_VF_COUNT_PER_GPU) 1879 { 1880 NV_PRINTF(LEVEL_ERROR, "No free free slot to track VF PCI info\n"); 1881 return NV_ERR_INVALID_STATE; 1882 } 1883 } 1884 } 1885 else if ((cmd == NV_VGPU_REMOVE_VF_PCI_INFO || cmd == NV_VGPU_REMOVE_VF_MDEV_INFO) && pPhysGpuInfo) 1886 { 1887 for (i = 0; i < MAX_VF_COUNT_PER_GPU; i++) 1888 { 1889 pVfInfo = &pPhysGpuInfo->vfPciInfo[i]; 1890 1891 if ((domain == pVfInfo->domain) && 1892 (bus == pVfInfo->bus) && 1893 (slot == pVfInfo->slot) && 1894 (function == pVfInfo->function)) 1895 { 1896 if (cmd == NV_VGPU_REMOVE_VF_PCI_INFO) 1897 { 1898 pVfInfo->isNvidiaAttached = NV_FALSE; 1899 } 1900 pVfInfo->isMdevAttached = NV_FALSE; 1901 break; 1902 } 1903 } 1904 1905 if (i == MAX_VF_COUNT_PER_GPU) 1906 { 1907 NV_PRINTF(LEVEL_ERROR, "Could not find entry for VF PCI info\n"); 1908 return NV_ERR_MISSING_TABLE_ENTRY; 1909 } 1910 } 1911 else if (cmd == NV_VGPU_GET_VF_INFO && vfPciInfo) 1912 { 1913 for (i = 0; i < MAX_VF_COUNT_PER_GPU; i++) 1914 { 1915 pVfInfo = &pPhysGpuInfo->vfPciInfo[i]; 1916 portMemCopy(&vfPciInfo[i], sizeof(vgpu_vf_pci_info), pVfInfo, sizeof(vgpu_vf_pci_info)); 1917 } 1918 } 1919 else 1920 { 1921 NV_PRINTF(LEVEL_ERROR, "Requested invalid operation on VF info\n"); 1922 status = NV_ERR_INVALID_ARGUMENT; 1923 } 1924 1925 return status; 1926 } 1927 1928 NV_STATUS 1929 kvgpumgrEnumerateVgpuPerPgpu(OBJGPU *pGpu, NV2080_CTRL_VGPU_MGR_INTERNAL_ENUMERATE_VGPU_PER_PGPU_PARAMS *pParams) 1930 { 1931 RM_API *pRmApi = GPU_GET_PHYSICAL_RMAPI(pGpu); 1932 1933 NV_CHECK_OK_OR_RETURN(LEVEL_ERROR, pRmApi->Control(pRmApi, pGpu->hInternalClient, pGpu->hInternalSubdevice, 1934 NV2080_CTRL_CMD_VGPU_MGR_INTERNAL_ENUMERATE_VGPU_PER_PGPU, 1935 pParams, sizeof(*pParams))); 1936 1937 return NV_OK; 1938 } 1939 1940 NV_STATUS 1941 kvgpumgrClearGuestVmInfo(OBJGPU *pGpu, KERNEL_HOST_VGPU_DEVICE *pKernelHostVgpuDevice) 1942 { 1943 NV2080_CTRL_VGPU_MGR_INTERNAL_CLEAR_GUEST_VM_INFO_PARAMS params; 1944 RM_API *pRmApi = GPU_GET_PHYSICAL_RMAPI(pGpu); 1945 NV_STATUS status; 1946 1947 portMemSet(¶ms, 0, sizeof(params)); 1948 params.gfid = pKernelHostVgpuDevice->gfid; 1949 1950 status = pRmApi->Control(pRmApi, pGpu->hInternalClient, pGpu->hInternalSubdevice, 1951 NV2080_CTRL_CMD_VGPU_MGR_INTERNAL_CLEAR_GUEST_VM_INFO, 1952 ¶ms, sizeof(params)); 1953 1954 if (status != NV_OK) 1955 NV_PRINTF(LEVEL_ERROR, "Failed to clear guest vm info on GSP\n"); 1956 1957 return status; 1958 } 1959 1960 NV_STATUS 1961 kvgpumgrGetHostVgpuDeviceFromGfid(NvU32 gpuPciId, NvU32 gfid, 1962 KERNEL_HOST_VGPU_DEVICE** ppHostVgpuDevice) 1963 { 1964 OBJSYS *pSys = SYS_GET_INSTANCE(); 1965 KernelVgpuMgr *pKernelVgpuMgr = SYS_GET_KERNEL_VGPUMGR(pSys); 1966 NvU32 pgpuIndex; 1967 KERNEL_PHYS_GPU_INFO *pPgpuInfo; 1968 KERNEL_HOST_VGPU_DEVICE *pKernelHostVgpuDevice; 1969 1970 NV_CHECK_OK_OR_RETURN(LEVEL_ERROR, kvgpumgrGetPgpuIndex(pKernelVgpuMgr, gpuPciId, &pgpuIndex)); 1971 pPgpuInfo = &pKernelVgpuMgr->pgpuInfo[pgpuIndex]; 1972 1973 if (!pPgpuInfo->sriovEnabled) 1974 return NV_ERR_NOT_SUPPORTED; 1975 1976 for (pKernelHostVgpuDevice = listHead(&(pPgpuInfo->listHostVgpuDeviceHead)); 1977 pKernelHostVgpuDevice != NULL; 1978 pKernelHostVgpuDevice = listNext(&(pPgpuInfo->listHostVgpuDeviceHead), pKernelHostVgpuDevice)) 1979 { 1980 if (pKernelHostVgpuDevice->gfid == gfid) 1981 { 1982 *ppHostVgpuDevice = pKernelHostVgpuDevice; 1983 return NV_OK; 1984 } 1985 } 1986 1987 return NV_ERR_OBJECT_NOT_FOUND; 1988 } 1989 1990 NV_STATUS 1991 kvgpumgrGetVgpuFbUsage(OBJGPU *pGpu, NVA081_CTRL_VGPU_CONFIG_GET_VGPU_FB_USAGE_PARAMS *pParams) 1992 { 1993 KERNEL_HOST_VGPU_DEVICE *pKernelHostVgpuDevice; 1994 NVA081_VGPU_FB_USAGE *pVgpuFbUsage; 1995 NvU32 i = 0; 1996 1997 NV_PRINTF(LEVEL_INFO, "%s\n", __FUNCTION__); 1998 1999 if (gpuIsSriovEnabled(pGpu)) 2000 { 2001 NV2080_CTRL_VGPU_MGR_INTERNAL_GET_VGPU_FB_USAGE_PARAMS internalParams; 2002 RM_API *pRmApi = GPU_GET_PHYSICAL_RMAPI(pGpu); 2003 2004 portMemSet(&internalParams, 0, sizeof(internalParams)); 2005 2006 NV_CHECK_OK_OR_RETURN(LEVEL_ERROR, pRmApi->Control(pRmApi, pGpu->hInternalClient, pGpu->hInternalSubdevice, 2007 NV2080_CTRL_CMD_VGPU_MGR_INTERNAL_GET_VGPU_FB_USAGE, 2008 &internalParams, sizeof(internalParams))); 2009 2010 if (internalParams.vgpuCount > NV_ARRAY_ELEMENTS(pParams->vgpuFbUsage)) 2011 return NV_ERR_INSUFFICIENT_RESOURCES; 2012 2013 for (i = 0; i < internalParams.vgpuCount; i++) 2014 { 2015 NV_CHECK_OK_OR_RETURN(LEVEL_ERROR, 2016 kvgpumgrGetHostVgpuDeviceFromGfid(pGpu->gpuId, internalParams.vgpuFbUsage[i].gfid, &pKernelHostVgpuDevice)); 2017 2018 pVgpuFbUsage = &pParams->vgpuFbUsage[i]; 2019 2020 portMemCopy(pVgpuFbUsage->vgpuUuid, VGPU_UUID_SIZE, pKernelHostVgpuDevice->vgpuUuid, VGPU_UUID_SIZE); 2021 2022 pVgpuFbUsage->fbUsed = internalParams.vgpuFbUsage[i].fbUsed; 2023 } 2024 2025 pParams->vgpuCount = internalParams.vgpuCount; 2026 } 2027 2028 return NV_OK; 2029 } 2030 2031 NV_STATUS 2032 kvgpumgrSetVgpuEncoderCapacity(OBJGPU *pGpu, NvU8 *vgpuUuid, NvU32 encoderCapacity) 2033 { 2034 OBJSYS *pSys = SYS_GET_INSTANCE(); 2035 KernelVgpuMgr *pKernelVgpuMgr = SYS_GET_KERNEL_VGPUMGR(pSys); 2036 KERNEL_HOST_VGPU_DEVICE *pKernelHostVgpuDevice; 2037 KERNEL_PHYS_GPU_INFO *pPhysGpuInfo; 2038 NvU32 i; 2039 2040 NV_PRINTF(LEVEL_INFO, "%s\n", __FUNCTION__); 2041 2042 NV_CHECK_OK_OR_RETURN(LEVEL_ERROR, kvgpumgrGetPgpuIndex(pKernelVgpuMgr, pGpu->gpuId, &i)); 2043 2044 pPhysGpuInfo = &pKernelVgpuMgr->pgpuInfo[i]; 2045 2046 for (pKernelHostVgpuDevice = listHead(&(pPhysGpuInfo->listHostVgpuDeviceHead)); 2047 pKernelHostVgpuDevice != NULL; 2048 pKernelHostVgpuDevice = listNext(&(pPhysGpuInfo->listHostVgpuDeviceHead), pKernelHostVgpuDevice)) 2049 { 2050 if (portMemCmp(pKernelHostVgpuDevice->vgpuUuid, vgpuUuid, VGPU_UUID_SIZE) == 0) 2051 break; 2052 } 2053 2054 if (pKernelHostVgpuDevice == NULL) 2055 return NV_ERR_OBJECT_NOT_FOUND; 2056 2057 if (gpuIsSriovEnabled(pGpu)) 2058 { 2059 NV2080_CTRL_VGPU_MGR_INTERNAL_SET_VGPU_ENCODER_CAPACITY_PARAMS params; 2060 RM_API *pRmApi = GPU_GET_PHYSICAL_RMAPI(pGpu); 2061 2062 params.gfid = pKernelHostVgpuDevice->gfid; 2063 params.encoderCapacity = encoderCapacity; 2064 2065 NV_CHECK_OK_OR_RETURN(LEVEL_ERROR, 2066 pRmApi->Control(pRmApi, pGpu->hInternalClient, pGpu->hInternalSubdevice, 2067 NV2080_CTRL_CMD_VGPU_MGR_INTERNAL_SET_VGPU_ENCODER_CAPACITY, 2068 ¶ms, sizeof(params))); 2069 } 2070 2071 return NV_OK; 2072 } 2073 2074 NV_STATUS 2075 kvgpumgrStart(const NvU8 *pMdevUuid, void *waitQueue, NvS32 *returnStatus, 2076 NvU8 *vmName, NvU32 qemuPid) 2077 { 2078 OBJSYS *pSys = SYS_GET_INSTANCE(); 2079 KernelVgpuMgr *pKernelVgpuMgr = SYS_GET_KERNEL_VGPUMGR(pSys); 2080 REQUEST_VGPU_INFO_NODE *pRequestVgpu = NULL; 2081 2082 for (pRequestVgpu = listHead(&(pKernelVgpuMgr->listRequestVgpuHead)); 2083 pRequestVgpu != NULL; 2084 pRequestVgpu = listNext(&(pKernelVgpuMgr->listRequestVgpuHead), pRequestVgpu)) 2085 { 2086 if (portMemCmp(pMdevUuid, pRequestVgpu->mdevUuid, VGPU_UUID_SIZE) == 0) 2087 { 2088 pRequestVgpu->waitQueue = waitQueue; 2089 pRequestVgpu->returnStatus = returnStatus; 2090 pRequestVgpu->vmName = vmName; 2091 pRequestVgpu->qemuPid = qemuPid; 2092 2093 CliAddSystemEvent(NV0000_NOTIFIERS_VM_START, 0); 2094 return NV_OK; 2095 } 2096 } 2097 return NV_ERR_OBJECT_NOT_FOUND; 2098 } 2099 2100 // 2101 // Add vGPU info received on mdev_create sysfs call to REQUEST_VGPU_INFO_NODE 2102 // list. REQUEST_VGPU_INFO_NODE is currently used only for vGPU on KVM. 2103 // 2104 // This funtion first checks whether the vGPU type is supported or not as 2105 // only homegeneous vGPU types are supported currently. Also, this function 2106 // only creates REQUEST_VGPU_INFO_NODE entry, actual vGPU will be created later 2107 // 2108 NV_STATUS 2109 kvgpumgrCreateRequestVgpu(NvU32 gpuPciId, const NvU8 *pMdevUuid, 2110 NvU32 vgpuTypeId, NvU16 *vgpuId, NvU32 gpuPciBdf) 2111 { 2112 OBJSYS *pSys = SYS_GET_INSTANCE(); 2113 OBJGPU *pGpu = gpumgrGetGpuFromId(gpuPciId); 2114 KernelVgpuMgr *pKernelVgpuMgr = SYS_GET_KERNEL_VGPUMGR(pSys); 2115 OBJHYPERVISOR *pHypervisor = SYS_GET_HYPERVISOR(pSys); 2116 NvU32 pgpuIndex; 2117 NV_STATUS status = NV_OK; 2118 VGPU_TYPE *vgpuTypeInfo; 2119 KERNEL_PHYS_GPU_INFO *pPhysGpuInfo; 2120 REQUEST_VGPU_INFO_NODE *pRequestVgpu = NULL; 2121 NvU32 allocFlags = NVOS32_ALLOC_FLAGS_FORCE_MEM_GROWS_UP; 2122 NvU64 vgpuIdSize = 1, tmpVgpuId; 2123 NvU8 devfn = gpuDecodeDevice(gpuPciBdf); 2124 NvU32 swizzId = KMIGMGR_SWIZZID_INVALID; 2125 2126 if (pGpu == NULL) 2127 { 2128 NV_PRINTF(LEVEL_ERROR, "GPU handle is not valid \n"); 2129 return NV_ERR_INVALID_STATE; 2130 } 2131 2132 if ((status = kvgpumgrGetPgpuIndex(pKernelVgpuMgr, gpuPciId, &pgpuIndex)) != NV_OK) 2133 return status; 2134 2135 pPhysGpuInfo = &(pKernelVgpuMgr->pgpuInfo[pgpuIndex]); 2136 2137 if ((status = kvgpumgrGetVgpuTypeInfo(vgpuTypeId, &vgpuTypeInfo)) != NV_OK) 2138 return status; 2139 2140 /* 2141 * For DriverVM, we will defer the createdVfMask validation later 2142 * during open call when the params provided. 2143 * 2144 */ 2145 2146 if (gpuIsSriovEnabled(pGpu) && 2147 !(pHypervisor->getProperty(pHypervisor, PDB_PROP_HYPERVISOR_DRIVERVM_ENABLED))) 2148 { 2149 NvU8 fnId = devfn - pGpu->sriovState.firstVFOffset; 2150 2151 NV_ASSERT_OR_RETURN((fnId < 64), NV_ERR_INVALID_ARGUMENT); 2152 2153 if (pPhysGpuInfo->createdVfMask & NVBIT64(fnId)) 2154 /* mdev device is already created on VF */ 2155 return NV_ERR_INVALID_OPERATION; 2156 } 2157 2158 if (IS_MIG_ENABLED(pGpu)) 2159 { 2160 NvU32 partitionFlag = PARTITIONID_INVALID; 2161 2162 NV_CHECK_OR_RETURN(LEVEL_INFO, 2163 IS_MIG_IN_USE(pGpu), 2164 NV_ERR_INVALID_OPERATION); 2165 2166 NV_ASSERT_OK_OR_RETURN( 2167 kvgpumgrGetPartitionFlag(vgpuTypeInfo->vgpuTypeId, &partitionFlag)); 2168 2169 NV_ASSERT_OK_OR_RETURN( 2170 kvgpumgrGetSwizzId(pGpu, pPhysGpuInfo, partitionFlag, &swizzId)); 2171 } 2172 else 2173 { 2174 // Creation request for a MIG vgpuType 2175 if (vgpuTypeInfo->gpuInstanceSize) 2176 return NV_ERR_INVALID_OPERATION; 2177 2178 status = kvgpumgrCheckVgpuTypeCreatable(pGpu, pPhysGpuInfo, vgpuTypeInfo); 2179 2180 if (status != NV_OK) 2181 return status; 2182 } 2183 2184 /* Initialize heap on first vGPU device creation */ 2185 if (pKernelVgpuMgr->pHeap == NULL) 2186 { 2187 NvU64 tmpSize; 2188 pKernelVgpuMgr->pHeap = portMemAllocNonPaged(sizeof(OBJEHEAP)); 2189 if (pKernelVgpuMgr->pHeap == NULL) 2190 { 2191 status = NV_ERR_NO_MEMORY; 2192 goto failed; 2193 } 2194 2195 constructObjEHeap(pKernelVgpuMgr->pHeap, 1, 0xFFFF + 1, 0, 0); 2196 2197 /* Verify if pHeap is allocated with required size */ 2198 pKernelVgpuMgr->pHeap->eheapGetSize(pKernelVgpuMgr->pHeap, &tmpSize); 2199 if (tmpSize != 0xFFFF) 2200 { 2201 pKernelVgpuMgr->pHeap->eheapDestruct(pKernelVgpuMgr->pHeap); 2202 portMemFree(pKernelVgpuMgr->pHeap); 2203 pKernelVgpuMgr->pHeap = NULL; 2204 status = NV_ERR_INSUFFICIENT_RESOURCES; 2205 goto failed; 2206 } 2207 } 2208 2209 status = pKernelVgpuMgr->pHeap->eheapAlloc(pKernelVgpuMgr->pHeap, 0xdeadbeef, &allocFlags, 2210 &tmpVgpuId, &vgpuIdSize, 1, 1, 2211 NULL, NULL, NULL); 2212 if (status != NV_OK) 2213 { 2214 NV_PRINTF(LEVEL_WARNING, 2215 "Failed to allocate heap for vGPU ID 0x%x\n", 2216 status); 2217 goto failed; 2218 } 2219 2220 *vgpuId = (NvU16) tmpVgpuId; 2221 pRequestVgpu = listPrependNew(&(pKernelVgpuMgr->listRequestVgpuHead)); 2222 if (pRequestVgpu == NULL) 2223 { 2224 status = NV_ERR_NO_MEMORY; 2225 goto failed; 2226 } 2227 2228 portMemSet(pRequestVgpu, 0, sizeof(REQUEST_VGPU_INFO_NODE)); 2229 2230 portMemCopy(pRequestVgpu->mdevUuid, VGPU_UUID_SIZE, pMdevUuid, VGPU_UUID_SIZE); 2231 pRequestVgpu->gpuPciId = gpuPciId; /* For SRIOV, this is PF's gpuPciId */ 2232 pRequestVgpu->vgpuId = *vgpuId; 2233 pRequestVgpu->gpuPciBdf = gpuPciBdf; /* For SRIOV, this is VF's gpuPciBdf */ 2234 2235 if (IS_MIG_IN_USE(pGpu)) 2236 { 2237 pRequestVgpu->swizzId = swizzId; 2238 } 2239 2240 kvgpumgrSetVgpuType(pGpu, pPhysGpuInfo, vgpuTypeId); 2241 pPhysGpuInfo->numCreatedVgpu++; 2242 2243 if (gpuGetDevice(pGpu) != devfn) /* SRIOV - VF */ 2244 pPhysGpuInfo->createdVfMask |= NVBIT64(devfn - pGpu->sriovState.firstVFOffset); 2245 2246 return NV_OK; 2247 2248 failed: 2249 if (swizzId != KMIGMGR_SWIZZID_INVALID) 2250 _kvgpumgrClearAssignedSwizzIdMask(pGpu, swizzId); 2251 2252 return status; 2253 } 2254 2255 // 2256 // Delete REQUEST_VGPU_INFO_NODE structure from list. 2257 // REQUEST_VGPU_INFO_NODE is currently used only for vGPU on KVM. 2258 // 2259 NV_STATUS 2260 kvgpumgrDeleteRequestVgpu(const NvU8 *pMdevUuid, NvU16 vgpuId) 2261 { 2262 OBJSYS *pSys = SYS_GET_INSTANCE(); 2263 OBJGPU *pGpu = NULL; 2264 NV_STATUS status; 2265 NvU32 pgpuIndex; 2266 KernelVgpuMgr *pKernelVgpuMgr = SYS_GET_KERNEL_VGPUMGR(pSys); 2267 REQUEST_VGPU_INFO_NODE *pRequestVgpu = NULL; 2268 REQUEST_VGPU_INFO_NODE *pRequestVgpuNext = NULL; 2269 NvU8 devfn = 0; 2270 2271 for (pRequestVgpu = listHead(&(pKernelVgpuMgr->listRequestVgpuHead)); 2272 pRequestVgpu != NULL; 2273 pRequestVgpu = pRequestVgpuNext) 2274 { 2275 pRequestVgpuNext = listNext(&(pKernelVgpuMgr->listRequestVgpuHead), pRequestVgpu); 2276 if (portMemCmp(pMdevUuid, pRequestVgpu->mdevUuid, VGPU_UUID_SIZE) == 0) 2277 { 2278 if ((status = kvgpumgrGetPgpuIndex(pKernelVgpuMgr, pRequestVgpu->gpuPciId, 2279 &pgpuIndex)) != NV_OK) 2280 return status; 2281 2282 pGpu = gpumgrGetGpuFromId(pRequestVgpu->gpuPciId); 2283 devfn = gpuDecodeDevice(pRequestVgpu->gpuPciBdf); 2284 2285 pKernelVgpuMgr->pgpuInfo[pgpuIndex].numCreatedVgpu--; 2286 2287 if (pGpu && (gpuGetDevice(pGpu) != devfn)) // SRIOV - VF 2288 pKernelVgpuMgr->pgpuInfo[pgpuIndex].createdVfMask &= ~(NVBIT64(devfn - pGpu->sriovState.firstVFOffset)); 2289 2290 if (IS_MIG_ENABLED(pGpu)) 2291 _kvgpumgrClearAssignedSwizzIdMask(pGpu, pRequestVgpu->swizzId); 2292 else if (pKernelVgpuMgr->pgpuInfo[pgpuIndex].numCreatedVgpu == 0) 2293 kvgpumgrSetVgpuType(pGpu, &pKernelVgpuMgr->pgpuInfo[pgpuIndex], NVA081_CTRL_VGPU_CONFIG_INVALID_TYPE); 2294 2295 pKernelVgpuMgr->pHeap->eheapFree(pKernelVgpuMgr->pHeap, vgpuId); 2296 2297 listRemove(&(pKernelVgpuMgr->listRequestVgpuHead), pRequestVgpu); 2298 2299 return NV_OK; 2300 } 2301 } 2302 return NV_ERR_OBJECT_NOT_FOUND; 2303 } 2304 2305 NV_STATUS 2306 kvgpumgrGetHostVgpuDeviceFromMdevUuid(NvU32 gpuPciId, const NvU8 *pMdevUuid, 2307 KERNEL_HOST_VGPU_DEVICE **ppKernelHostVgpuDevice) 2308 { 2309 OBJSYS *pSys = SYS_GET_INSTANCE(); 2310 KernelVgpuMgr *pKernelVgpuMgr = SYS_GET_KERNEL_VGPUMGR(pSys); 2311 NvU32 pgpuIndex , rmStatus; 2312 KERNEL_PHYS_GPU_INFO *pPgpuInfo; 2313 KERNEL_HOST_VGPU_DEVICE *pKernelHostVgpuDevice; 2314 2315 if ((rmStatus = kvgpumgrGetPgpuIndex(pKernelVgpuMgr, gpuPciId, &pgpuIndex)) != NV_OK) 2316 return rmStatus; 2317 2318 pPgpuInfo = &pKernelVgpuMgr->pgpuInfo[pgpuIndex]; 2319 2320 for (pKernelHostVgpuDevice = listHead(&(pPgpuInfo->listHostVgpuDeviceHead)); 2321 pKernelHostVgpuDevice != NULL; 2322 pKernelHostVgpuDevice = listNext(&(pPgpuInfo->listHostVgpuDeviceHead), pKernelHostVgpuDevice)) 2323 { 2324 if (pKernelHostVgpuDevice == NULL || pKernelHostVgpuDevice->pRequestVgpuInfoNode == NULL) 2325 return NV_ERR_INVALID_POINTER; 2326 2327 if (portMemCmp(pKernelHostVgpuDevice->pRequestVgpuInfoNode->mdevUuid, 2328 pMdevUuid, VM_UUID_SIZE) == 0) 2329 { 2330 *ppKernelHostVgpuDevice = pKernelHostVgpuDevice; 2331 return NV_OK; 2332 } 2333 } 2334 NV_PRINTF(LEVEL_ERROR, "Object not found\n"); 2335 return NV_ERR_OBJECT_NOT_FOUND; 2336 } 2337 2338 NV_STATUS 2339 kvgpumgrGetHostVgpuDeviceFromVgpuUuid(NvU32 gpuPciId, NvU8 *vgpuUuid, 2340 KERNEL_HOST_VGPU_DEVICE **ppKernelHostVgpuDevice) 2341 { 2342 OBJSYS *pSys = SYS_GET_INSTANCE(); 2343 KernelVgpuMgr *pKernelVgpuMgr = SYS_GET_KERNEL_VGPUMGR(pSys); 2344 NvU32 pgpuIndex; 2345 KERNEL_PHYS_GPU_INFO *pPgpuInfo; 2346 KERNEL_HOST_VGPU_DEVICE *pKernelHostVgpuDevice; 2347 2348 NV_CHECK_OK_OR_RETURN(LEVEL_ERROR, kvgpumgrGetPgpuIndex(pKernelVgpuMgr, gpuPciId, &pgpuIndex)); 2349 2350 pPgpuInfo = &pKernelVgpuMgr->pgpuInfo[pgpuIndex]; 2351 2352 for (pKernelHostVgpuDevice = listHead(&(pPgpuInfo->listHostVgpuDeviceHead)); 2353 pKernelHostVgpuDevice != NULL; 2354 pKernelHostVgpuDevice = listNext(&(pPgpuInfo->listHostVgpuDeviceHead), pKernelHostVgpuDevice)) 2355 { 2356 if (portMemCmp(pKernelHostVgpuDevice->vgpuUuid, 2357 vgpuUuid, VM_UUID_SIZE) == 0) 2358 { 2359 *ppKernelHostVgpuDevice = pKernelHostVgpuDevice; 2360 return NV_OK; 2361 } 2362 } 2363 2364 return NV_ERR_OBJECT_NOT_FOUND; 2365 } 2366 2367 /* 2368 * On 1GB profiles on 48GB board, we do not deduct any reserved fb from vGPU FB length 2369 * as maxInstance is only 32, so guest complete 1GB of fb mem. In such cases with 2370 * heterogeneous vGPUs, for such 1G profiles on 48G board, some combinations with 2371 * other vGPU types do not work. 2372 * Due to this, A40-8Q at placement Id 0 cannot work with A40-1Q at placement Id 8 since 2373 * A40-1Q is occupying larger vGPU FB length and overlaps with A40-8Q's assigned FB. 2374 * Similar scenario happens for A40-8Q at placement Id 24 and A40-1Q at placement Id 32 2375 * So, we disable 1GB profiles in such cases at placement Id 8 and placement Id 32. 2376 */ 2377 static NvBool 2378 _kvgpumgrIsPlacementValid(OBJGPU *pGpu, KERNEL_PHYS_GPU_INFO *pPgpuInfo, NvU32 vgpuTypeIndex, 2379 NvU32 placementId) 2380 { 2381 NvU64 vgpuFbLength; 2382 NvU32 denyListAdaHopper[] = {2, 3, 8, 9, 14, 15, 20, 21, 26, 27, 32, 33, 38, 39, 44, 45}; 2383 NvU32 denyListAmpere[] = {8, 32}; 2384 NvU32 i, length, *invalidPlacements; 2385 2386 if (IS_GSP_CLIENT(pGpu)) 2387 { 2388 invalidPlacements = denyListAdaHopper; 2389 length = sizeof(denyListAdaHopper) / sizeof(NvU32); 2390 } 2391 else 2392 { 2393 invalidPlacements = denyListAmpere; 2394 length = sizeof(denyListAmpere) / sizeof(NvU32); 2395 } 2396 2397 vgpuFbLength = pPgpuInfo->guestVmmuCount[vgpuTypeIndex] * gpuGetVmmuSegmentSize(pGpu); 2398 2399 if (vgpuFbLength == VGPU_LOWER_FB_PROFILE_SIZE_1_GB) 2400 { 2401 for (i = 0; i < length; i++) 2402 { 2403 if (invalidPlacements[i] == placementId) 2404 return NV_FALSE; 2405 } 2406 } 2407 2408 return NV_TRUE; 2409 } 2410 2411 /* 2412 * This function recursively divides the placement region in 1/2, 1/4, 1/8, 1/16 partitions 2413 * and then calculates the placement IDs of each vGPU type. It will try to allocate 2414 * placement ID of 2 vGPU instances for a type in such a way that the placement ID 2415 * of first vGPU instance starts at the beginning of partition and the placement ID 2416 * of second vGPU instance ends at the end of partition. 2417 * 2418 * It finds the vGPU types whose 2 instances can be allocated in a 1/2, 1/4, 1/8, 1/16 2419 * partition and then allocates one at start of partition and other at end of partion. 2420 * 2421 * It does this recursively by taking input start and end as input alongwith the current 2422 * partition which specifies whether this is 1/1, 1/2, 1/4, 1/8, 1/16 partion. 2423 * 2424 * Similarly it also calculates the channel offsets for each supported placementId 2425 * for a vGPU type. The algorithm for calculating placementId and channel offset 2426 * is the same just that for channel offset the range is from 0 to 2048. 2427 * 2428 * For vGPU-GSP, we also need to define offsets in FB for GSP plugin heap. 2429 * For larger vGPU profiles with GSP plugin heap >=1 vMMU segment, the gsp heap is 2430 * placed at the end of vGPU FB. 2431 * For smaller profiles with gsp heap < 1 vMMU segment, heap is placed at end of 2432 * each 1/4th alignment (for 128MB vMMU segment size) OR 1/8th alighment (for 64MB 2433 * vMMU segment size). For such profiles the vMMU segment at the end of 1/4 or 1/8 2434 * partition is divided as per profile's heap size. 2435 * 2436 */ 2437 static void 2438 _kvgpumgrSetHeterogeneousResources(OBJGPU *pGpu, KERNEL_PHYS_GPU_INFO *pPgpuInfo, NvU32 placementIdMin, 2439 NvU32 placementIdMax, NvU32 chidMin, NvU32 chidMax, 2440 NvU32 vmmuSegMin, NvU32 vmmuSegMax, NvU64 gspHeapOffsetMin, 2441 NvU64 gspHeapOffsetMax, NvU32 partitionCount, 2442 NvBool isLeftPartition) 2443 { 2444 VGPU_TYPE *pVgpuTypeInfo; 2445 NvU32 heterogeneousMaxInstance, i; 2446 NvBool isCarveOutGspHeap = NV_FALSE; 2447 NvU64 newVmmuSegMin, newVmmuSegMax, newGspHeapOffsetMin, newGspHeapOffsetMax, vmmuSegSize; 2448 NvBool isDefineLeftPlacement, isDefineRightPlacement; 2449 2450 /* 2451 * As max vGPU per GPU is 32, the minimum partition for 2 vGPUs will be 16. 2452 * So, if this is a 1/16 partition, don't recurse further 2453 */ 2454 if (partitionCount > MAX_VGPU_DEVICES_PER_PGPU / 2) 2455 return; 2456 2457 vmmuSegSize = gpuGetVmmuSegmentSize(pGpu); 2458 for (i = 0; i < pPgpuInfo->numVgpuTypes; i++) 2459 { 2460 pVgpuTypeInfo = pPgpuInfo->vgpuTypes[i]; 2461 2462 if (pVgpuTypeInfo->placementSize == 0) 2463 continue; 2464 2465 isDefineLeftPlacement = NV_FALSE; 2466 isDefineRightPlacement = NV_FALSE; 2467 2468 heterogeneousMaxInstance = nvPrevPow2_U32(pVgpuTypeInfo->maxInstance); 2469 2470 /* 2471 * If homogeneous maxInstances of vGPU type are in power-of-2 and can fit in this partition, 2472 * then define both the placements in this recursive call 2473 */ 2474 if (partitionCount * 2 == pVgpuTypeInfo->maxInstance) 2475 { 2476 isDefineLeftPlacement = NV_TRUE; 2477 isDefineRightPlacement = NV_TRUE; 2478 2479 /* 2480 * Check if the next recursive partition will be a smaller partition for which 2481 * we need to carve out GSP heap at the end of smaller partition. 2482 */ 2483 if (IS_GSP_CLIENT(pGpu) && (isCarveOutGspHeap == NV_FALSE) && 2484 (pVgpuTypeInfo->gspHeapSize == vmmuSegSize)) 2485 isCarveOutGspHeap = NV_TRUE; 2486 } 2487 else if (((heterogeneousMaxInstance < pVgpuTypeInfo->maxInstance) && 2488 (heterogeneousMaxInstance == partitionCount)) || 2489 ((partitionCount == 1) && (pVgpuTypeInfo->maxInstance == 1))) 2490 { 2491 /* 2492 * If only one instance of vGPU type can fit in this partition, then define 2493 * placement depending on whether it is a left or right partition 2494 */ 2495 isDefineLeftPlacement = isLeftPartition; 2496 isDefineRightPlacement = !isLeftPartition; 2497 } 2498 2499 2500 if (isDefineLeftPlacement == NV_TRUE) 2501 { 2502 /* 2503 * Fill placement ID / channel / FB offset of first vGPU in this partition 2504 * First vGPU is aligned to the starting of partition 2505 */ 2506 if (_kvgpumgrIsPlacementValid(pGpu, pPgpuInfo, i, placementIdMin)) 2507 { 2508 pVgpuTypeInfo->supportedPlacementIds[pVgpuTypeInfo->placementCount] = placementIdMin; 2509 pVgpuTypeInfo->supportedChidOffsets[pVgpuTypeInfo->placementCount] = chidMin; 2510 2511 if (!IS_GSP_CLIENT(pGpu)) 2512 pPgpuInfo->supportedVmmuOffsets[i][pVgpuTypeInfo->placementCount] = vmmuSegMin; 2513 else 2514 { 2515 /* If profile occupies > 1 vMMU segment for GSP heap, place heap at end of vGPU FB. */ 2516 if (pVgpuTypeInfo->gspHeapSize >= vmmuSegSize) 2517 { 2518 pPgpuInfo->supportedVmmuOffsets[i][pVgpuTypeInfo->placementCount] = vmmuSegMin; 2519 pPgpuInfo->gspHeapOffsets[i][pVgpuTypeInfo->placementCount] = 2520 (vmmuSegMin + pPgpuInfo->guestVmmuCount[i]) * vmmuSegSize; 2521 } 2522 else 2523 { 2524 /* 2525 * If we're in smaller parition, GSP vMMU segment will be input to the function. 2526 * Place the gsp heap of first vGPU at the starting of the GSP vMMU segment. 2527 */ 2528 pPgpuInfo->supportedVmmuOffsets[i][pVgpuTypeInfo->placementCount] = vmmuSegMin; 2529 pPgpuInfo->gspHeapOffsets[i][pVgpuTypeInfo->placementCount] = gspHeapOffsetMin; 2530 } 2531 2532 /* For 32:1 vGPU types, the GSP heap is placed between 2 consecutive guest vMMU segments */ 2533 if (heterogeneousMaxInstance == 32) 2534 { 2535 pPgpuInfo->supportedVmmuOffsets[i][pVgpuTypeInfo->placementCount] = vmmuSegMin; 2536 pPgpuInfo->gspHeapOffsets[i][pVgpuTypeInfo->placementCount] = 2537 (vmmuSegMin + pPgpuInfo->guestVmmuCount[i]) * vmmuSegSize; 2538 } 2539 } 2540 2541 pVgpuTypeInfo->placementCount++; 2542 } 2543 } 2544 2545 if (isDefineRightPlacement == NV_TRUE) 2546 { 2547 /* 2548 * Fill placement ID / channel / FB offset of second vGPU in this partition 2549 * Second vGPU is aligned to the end of partition 2550 */ 2551 if (_kvgpumgrIsPlacementValid(pGpu, pPgpuInfo, i, 2552 placementIdMax - pVgpuTypeInfo->placementSize)) 2553 { 2554 pVgpuTypeInfo->supportedPlacementIds[pVgpuTypeInfo->placementCount] = 2555 placementIdMax - pVgpuTypeInfo->placementSize; 2556 2557 pVgpuTypeInfo->supportedChidOffsets[pVgpuTypeInfo->placementCount] = 2558 chidMax - pVgpuTypeInfo->channelCount; 2559 2560 if (!IS_GSP_CLIENT(pGpu)) 2561 pPgpuInfo->supportedVmmuOffsets[i][pVgpuTypeInfo->placementCount] = 2562 vmmuSegMax - pPgpuInfo->guestVmmuCount[i]; 2563 else 2564 { 2565 /* If profile occupies > 1 vMMU segment for GSP heap, place heap at end of vGPU FB. */ 2566 if (pVgpuTypeInfo->gspHeapSize >= vmmuSegSize) 2567 { 2568 pPgpuInfo->supportedVmmuOffsets[i][pVgpuTypeInfo->placementCount] = 2569 vmmuSegMax - pPgpuInfo->guestVmmuCount[i] - (pVgpuTypeInfo->gspHeapSize / vmmuSegSize); 2570 pPgpuInfo->gspHeapOffsets[i][pVgpuTypeInfo->placementCount] = 2571 (vmmuSegMax * vmmuSegSize) - pVgpuTypeInfo->gspHeapSize; 2572 } 2573 else 2574 { 2575 /* 2576 * If we're in smaller parition, GSP vMMU segment will be input to the function. 2577 * Place the gsp heap of first vGPU at the starting of the GSP vMMU segment. 2578 */ 2579 pPgpuInfo->supportedVmmuOffsets[i][pVgpuTypeInfo->placementCount] = 2580 vmmuSegMax - pPgpuInfo->guestVmmuCount[i]; 2581 pPgpuInfo->gspHeapOffsets[i][pVgpuTypeInfo->placementCount] = 2582 gspHeapOffsetMax - pVgpuTypeInfo->gspHeapSize; 2583 } 2584 2585 /* For 32:1 vGPU types, the GSP heap is placed between 2 consecutive guest vMMU segments */ 2586 if (heterogeneousMaxInstance == 32) 2587 { 2588 pPgpuInfo->supportedVmmuOffsets[i][pVgpuTypeInfo->placementCount] = 2589 vmmuSegMax - pPgpuInfo->guestVmmuCount[i]; 2590 pPgpuInfo->gspHeapOffsets[i][pVgpuTypeInfo->placementCount] = 2591 ((vmmuSegMax - pPgpuInfo->guestVmmuCount[i]) * vmmuSegSize) - pVgpuTypeInfo->gspHeapSize; 2592 } 2593 } 2594 2595 pVgpuTypeInfo->placementCount++; 2596 } 2597 } 2598 } 2599 2600 /* 2601 * If the next recursive partition is for a left smaller partition which has GSP heap at 2602 * of start of partition, then update vmmuSegMin to reserve one segment at the 2603 * start of smaller partition. Also, init gsp min/max value for the reserved vMMU segment 2604 * at the start. 2605 */ 2606 newVmmuSegMax = ((vmmuSegMin + vmmuSegMax) / 2); 2607 if ((isCarveOutGspHeap == NV_TRUE)) 2608 { 2609 NV_ASSERT((gspHeapOffsetMin == 0)); 2610 2611 newVmmuSegMin = vmmuSegMin + 1; 2612 newGspHeapOffsetMin = vmmuSegMin * vmmuSegSize; 2613 newGspHeapOffsetMax = newGspHeapOffsetMin + vmmuSegSize; 2614 } 2615 else 2616 { 2617 newVmmuSegMin = vmmuSegMin; 2618 newGspHeapOffsetMin = gspHeapOffsetMin; 2619 newGspHeapOffsetMax = (gspHeapOffsetMin + gspHeapOffsetMax) / 2; 2620 } 2621 2622 /* Recursively call to get placment ID in left half of this partition */ 2623 _kvgpumgrSetHeterogeneousResources(pGpu, pPgpuInfo, placementIdMin, 2624 (placementIdMin + placementIdMax) / 2, 2625 chidMin, (chidMin + chidMax) / 2, newVmmuSegMin, 2626 newVmmuSegMax, newGspHeapOffsetMin, newGspHeapOffsetMax, partitionCount * 2, 2627 NV_TRUE); 2628 2629 /* 2630 * If the next recursive partition is for a right smaller partition which has GSP heap at 2631 * of end of partition, then update vmmuSegMax to reserve one segment at the 2632 * end of right partition. Also, init gsp min/max value for the reserved vMMU segment 2633 * at the end. 2634 */ 2635 newVmmuSegMin = (vmmuSegMin + vmmuSegMax) / 2; 2636 if ((isCarveOutGspHeap == NV_TRUE)) 2637 { 2638 newVmmuSegMax = vmmuSegMax - 1; 2639 newGspHeapOffsetMin = newVmmuSegMax * vmmuSegSize; 2640 newGspHeapOffsetMax = newGspHeapOffsetMin + vmmuSegSize; 2641 } 2642 else 2643 { 2644 newVmmuSegMax = vmmuSegMax; 2645 newGspHeapOffsetMin = (gspHeapOffsetMin + gspHeapOffsetMax) / 2;; 2646 newGspHeapOffsetMax = gspHeapOffsetMax; 2647 } 2648 2649 /* Recursively call to get placment ID in right half of this partition */ 2650 _kvgpumgrSetHeterogeneousResources(pGpu, pPgpuInfo, (placementIdMin + placementIdMax) / 2, 2651 placementIdMax, (chidMin + chidMax) / 2, 2652 chidMax, newVmmuSegMin, newVmmuSegMax, 2653 newGspHeapOffsetMin, newGspHeapOffsetMax, partitionCount * 2, 2654 NV_FALSE); 2655 } 2656 2657 NV_STATUS 2658 kvgpumgrSetSupportedPlacementIds(OBJGPU *pGpu) 2659 { 2660 OBJSYS *pSys = SYS_GET_INSTANCE(); 2661 KernelVgpuMgr *pKernelVgpuMgr = SYS_GET_KERNEL_VGPUMGR(pSys); 2662 KernelFifo *pKernelFifo = GPU_GET_KERNEL_FIFO(pGpu); 2663 MemoryManager *pMemoryManager = GPU_GET_MEMORY_MANAGER(pGpu); 2664 NV_STATUS rmStatus = NV_OK; 2665 KERNEL_PHYS_GPU_INFO *pPgpuInfo; 2666 NvU32 index, i; 2667 VGPU_TYPE *pVgpuTypeInfo; 2668 NvU32 hostChannelCount = 0, totalVmmuCount = 0; 2669 NvU64 totalReservedFb, vgpuReservedFb, guestFbLength, totalAvailableFb, totalRequiredFb; 2670 NvU64 gspHeapOffsetMax, gspHeapOffsetMin, pmaRegionLength, pmaBaseOffset, largestOffset; 2671 NvU64 vmmuOffsetMin, vmmuOffsetMax, vmmuSegmentMin, vmmuSegmentMax; 2672 Heap *pHeap = GPU_GET_HEAP(pGpu); 2673 2674 NV_CHECK_OK_OR_RETURN(LEVEL_ERROR, 2675 kvgpumgrGetPgpuIndex(pKernelVgpuMgr, pGpu->gpuId, &index)); 2676 2677 pPgpuInfo = &(pKernelVgpuMgr->pgpuInfo[index]); 2678 2679 pPgpuInfo->heterogeneousTimesliceSizesSupported = NV_FALSE; 2680 2681 /* Initially, heterogeneous vgpus enabled only for sriov vGPUs on VMware/KVM */ 2682 if (gpuIsSriovEnabled(pGpu)) 2683 { 2684 if (osIsVgpuVfioPresent() == NV_OK) 2685 pPgpuInfo->heterogeneousTimesliceSizesSupported = NV_TRUE; 2686 } 2687 2688 if (!pPgpuInfo->heterogeneousTimesliceSizesSupported) 2689 return rmStatus; 2690 2691 hostChannelCount = kfifoChidMgrGetNumChannels(pGpu, pKernelFifo, pKernelFifo->ppChidMgr[0]); 2692 2693 for (i = 0; i < pPgpuInfo->numVgpuTypes; i++) 2694 { 2695 pVgpuTypeInfo = pPgpuInfo->vgpuTypes[i]; 2696 if (pVgpuTypeInfo == NULL) 2697 break; 2698 2699 /* Set to NVA081_PLACEMENT_ID_INVALID initially */ 2700 portMemSet(pVgpuTypeInfo->supportedPlacementIds, NV_U8_MAX, 2701 sizeof(pVgpuTypeInfo->supportedPlacementIds)); 2702 2703 /* Ignore MIG vGPUs, only used for timesliced vGPUs */ 2704 if (pVgpuTypeInfo->gpuInstanceSize != 0) 2705 { 2706 pVgpuTypeInfo->placementSize = 0; 2707 continue; 2708 } 2709 2710 pVgpuTypeInfo->placementCount = 0; 2711 pPgpuInfo->guestVmmuCount[i] = 0; 2712 pVgpuTypeInfo->placementSize = pVgpuTypeInfo->profileSize / (1024 * 1024 * 1024); 2713 2714 if (gpuIsSriovEnabled(pGpu)) 2715 { 2716 if (!gpuIsNonPowerOf2ChannelCountSupported(pGpu)) 2717 pVgpuTypeInfo->channelCount = nvPrevPow2_U32(hostChannelCount / 2718 pVgpuTypeInfo->maxInstance); 2719 2720 /* 2721 * For sriov vGPUs with GSP disabled, guest FB length is only dependent on 2722 * profile fb length and RM reserved fb (including ECC). Calculate the 2723 * guest fb length here by reducing reserved FB from profile fb length 2724 * depending on max instance and aligning it to VMMU segment size. 2725 */ 2726 if (!IS_GSP_CLIENT(pGpu)) 2727 { 2728 totalReservedFb = memmgrGetVgpuHostRmReservedFb_HAL(pGpu, 2729 pMemoryManager, pVgpuTypeInfo->vgpuTypeId) + 2730 kvgpumgrGetEccAndPrReservedFb(pGpu); 2731 2732 vgpuReservedFb = NV_ALIGN_UP((totalReservedFb / pVgpuTypeInfo->maxInstance), 2733 gpuGetVmmuSegmentSize(pGpu)); 2734 2735 /* 2736 * For 1GB profiles on 48GB board, maxInstances is limited to 32. For such 2737 * profiles, there is no per vgpu reserved fb carved out from guest fb as 2738 * host has space for reserved fb. 2739 */ 2740 if (pVgpuTypeInfo->profileSize == VGPU_LOWER_FB_PROFILE_SIZE_1_GB) 2741 { 2742 heapGetUsableSize(pHeap, &totalAvailableFb); 2743 2744 /* Total FB needed if vgpu reserved fb is 0 and not carved from guest fb */ 2745 totalRequiredFb = pVgpuTypeInfo->maxInstance * 2746 (VGPU_LOWER_FB_PROFILE_SIZE_1_GB + vgpuReservedFb); 2747 2748 if (totalRequiredFb < totalAvailableFb) 2749 vgpuReservedFb = 0; 2750 } 2751 2752 guestFbLength = pVgpuTypeInfo->profileSize - vgpuReservedFb; 2753 2754 pPgpuInfo->guestVmmuCount[i] = guestFbLength / gpuGetVmmuSegmentSize(pGpu); 2755 } 2756 else 2757 { 2758 /* Calculate the guest FB using similar calculation as done in vGPU plugin */ 2759 totalAvailableFb = pMemoryManager->Ram.fbTotalMemSizeMb << 20; 2760 totalAvailableFb = NV_ALIGN_UP(totalAvailableFb, 8 * gpuGetVmmuSegmentSize(pGpu)); 2761 2762 guestFbLength = (totalAvailableFb / pVgpuTypeInfo->maxInstance) - 2763 pVgpuTypeInfo->fbReservation - pVgpuTypeInfo->gspHeapSize; 2764 guestFbLength = NV_MIN(guestFbLength, pVgpuTypeInfo->fbLength); 2765 guestFbLength = NV_ALIGN_DOWN(guestFbLength, gpuGetVmmuSegmentSize(pGpu)); 2766 2767 pPgpuInfo->guestVmmuCount[i] = guestFbLength / gpuGetVmmuSegmentSize(pGpu); 2768 } 2769 } 2770 2771 if (pVgpuTypeInfo->maxInstance == 1) 2772 { 2773 pPgpuInfo->placementRegionSize = pVgpuTypeInfo->placementSize; 2774 2775 if (pPgpuInfo->guestVmmuCount[i]) 2776 { 2777 totalVmmuCount = pPgpuInfo->guestVmmuCount[i]; 2778 2779 if (IS_GSP_CLIENT(pGpu)) 2780 totalVmmuCount += (pVgpuTypeInfo->gspHeapSize / gpuGetVmmuSegmentSize(pGpu)); 2781 } 2782 } 2783 } 2784 2785 /* 2786 * For SRIOV, the placement IDs are aligned to 1/2, 1/4, 1/8, 1/16 partitions 2787 * due to restrictions on channels assigned to VF being in power-of-2. 2788 * TODO : Define placement IDs for legacy vGPUs which do not have 2789 * power-of-2 channel restriction 2790 */ 2791 if (gpuIsSriovEnabled(pGpu)) 2792 { 2793 pmaGetLargestFree(&pHeap->pmaObject, &pmaRegionLength, 2794 &pmaBaseOffset, &largestOffset); 2795 2796 vmmuOffsetMin = NV_ALIGN_UP(pmaBaseOffset, gpuGetVmmuSegmentSize(pGpu)); 2797 vmmuOffsetMax = pmaBaseOffset + pmaRegionLength; 2798 2799 totalRequiredFb = (totalVmmuCount * gpuGetVmmuSegmentSize(pGpu)); 2800 if ((vmmuOffsetMax - vmmuOffsetMin) < totalRequiredFb) 2801 { 2802 NV_PRINTF(LEVEL_ERROR, "Required FB for heterogeneous vGPU (%llu) less " 2803 "than available FB (%llu)\n", totalRequiredFb, pmaRegionLength); 2804 NV_ASSERT(0); 2805 2806 // Disable heterogeneous vGPU support, but return success to allow homogeneous vGPUs. 2807 pPgpuInfo->heterogeneousTimesliceSizesSupported = NV_FALSE; 2808 return NV_OK; 2809 } 2810 2811 vmmuSegmentMin = vmmuOffsetMin / gpuGetVmmuSegmentSize(pGpu); 2812 vmmuSegmentMax = vmmuSegmentMin + totalVmmuCount; 2813 2814 gspHeapOffsetMin = 0; 2815 gspHeapOffsetMax = 0; 2816 2817 _kvgpumgrSetHeterogeneousResources(pGpu, pPgpuInfo, 0, pPgpuInfo->placementRegionSize, 2818 0, hostChannelCount, vmmuSegmentMin, vmmuSegmentMax, 2819 gspHeapOffsetMin, gspHeapOffsetMax, 1, NV_TRUE); 2820 } 2821 2822 return rmStatus; 2823 } 2824 2825 static NvBool 2826 isPlacementOverlapping(NvU16 minId1, NvU16 maxId1, NvU16 id2, NvU16 size2) 2827 { 2828 NvU16 max, min, size1; 2829 2830 min = NV_MIN(minId1, id2); 2831 max = NV_MAX(maxId1, (id2 + size2)); 2832 size1 = maxId1 - minId1; 2833 2834 if ((size1 + size2) > (max - min)) 2835 return NV_TRUE; 2836 2837 return NV_FALSE; 2838 } 2839 2840 static NvBool 2841 isPlacementSubset(NvU16 min, NvU16 max, NvU16 id, NvU16 size) 2842 { 2843 if ((min <= id) && (max >= (id + size - 1))) 2844 return NV_TRUE; 2845 2846 return NV_FALSE; 2847 } 2848 2849 static NV_STATUS 2850 _kvgpumgrUpdateCreatablePlacementIds(OBJGPU *pGpu, NvU16 placementId, NvU32 vgpuTypeId, NvBool isAlloc) 2851 { 2852 OBJSYS *pSys = SYS_GET_INSTANCE(); 2853 KernelVgpuMgr *pKernelVgpuMgr = SYS_GET_KERNEL_VGPUMGR(pSys); 2854 KERNEL_PHYS_GPU_INFO *pPgpuInfo; 2855 VGPU_TYPE *pVgpuTypeInfo; 2856 NvU32 index, i , j, placementSize, min = 0, max = 0, numCreatable = 0; 2857 NV_RANGE range; 2858 NvBool isVgpuTypeCreatable; 2859 2860 NV_CHECK_OK_OR_RETURN(LEVEL_ERROR, 2861 kvgpumgrGetPgpuIndex(pKernelVgpuMgr, pGpu->gpuId, &index)); 2862 2863 NV_CHECK_OK_OR_RETURN(LEVEL_ERROR, 2864 kvgpumgrGetVgpuTypeInfo(vgpuTypeId, &pVgpuTypeInfo)); 2865 2866 pPgpuInfo = &(pKernelVgpuMgr->pgpuInfo[index]); 2867 placementSize = pVgpuTypeInfo->placementSize; 2868 2869 range = rangeMake(placementId, placementId + placementSize - 1); 2870 2871 if (isAlloc) 2872 { 2873 /* Update the placment region bitmap to set (id + size) slots */ 2874 bitVectorSetRange(&pPgpuInfo->usedPlacementRegionMap, range); 2875 min = placementId; 2876 max = placementId + placementSize; 2877 } 2878 else 2879 { 2880 /* Update the placment region bitmap to unset (id + size) slots */ 2881 bitVectorClrRange(&pPgpuInfo->usedPlacementRegionMap, range); 2882 2883 /* find the minimum slot before placement ID which is not occupied */ 2884 min = placementId; 2885 for (j = placementId; j > 0;) 2886 { 2887 j--; 2888 2889 if (bitVectorTest(&pPgpuInfo->usedPlacementRegionMap, j)) 2890 break; 2891 2892 min = j; 2893 } 2894 2895 /* find the maximum slot after placement ID + placementSize which is not occupied */ 2896 max = placementId + placementSize - 1; 2897 for (j = placementId + placementSize; j < pPgpuInfo->placementRegionSize; j++) 2898 { 2899 if (bitVectorTest(&pPgpuInfo->usedPlacementRegionMap, j)) 2900 break; 2901 2902 max = j; 2903 } 2904 } 2905 2906 for (i = 0; i < MAX_VGPU_TYPES_PER_PGPU; i++) 2907 pPgpuInfo->supportedTypeIds[i] = NVA081_CTRL_VGPU_CONFIG_INVALID_TYPE; 2908 2909 /* Update creatable placement Ids of all vGPU type IDs */ 2910 for (i = 0; i < pPgpuInfo->numVgpuTypes; i++) 2911 { 2912 pVgpuTypeInfo = pPgpuInfo->vgpuTypes[i]; 2913 if (pVgpuTypeInfo == NULL) 2914 break; 2915 2916 if (pVgpuTypeInfo->placementSize == 0) 2917 continue; 2918 2919 isVgpuTypeCreatable = NV_FALSE; 2920 2921 for (j = 0; j < pVgpuTypeInfo->placementCount; j++) 2922 { 2923 /* 2924 * Creatable Placement IDs will be updated either on VM boot or VM shutdown. 2925 * 1. VM boot. 2926 * Here, we compare every (id + size) of each vGPU type if it's partial/full 2927 * overlapping with the (id + size) of the vGPU VM that is booting up. 2928 * If yes, then mark that placement ID as INVALID. 2929 * 2. VM shutdown 2930 * Here, we compare every INVALID id of each vGPU type and 2931 * see if the corresponding supported (id + size) is a complete subset 2932 * of (max - min) range of available placement slots. 2933 * If it is subset, then the INVALID id is overwritten with 2934 * corresponding supported id as it is now creatable. 2935 */ 2936 if (pPgpuInfo->creatablePlacementIds[i][j] != NVA081_PLACEMENT_ID_INVALID) 2937 { 2938 if (isAlloc && isPlacementOverlapping(min, max, 2939 pPgpuInfo->creatablePlacementIds[i][j], 2940 pVgpuTypeInfo->placementSize)) 2941 pPgpuInfo->creatablePlacementIds[i][j] = NVA081_PLACEMENT_ID_INVALID; 2942 2943 } 2944 else 2945 { 2946 if (!isAlloc && isPlacementSubset(min, max, pVgpuTypeInfo->supportedPlacementIds[j], 2947 pVgpuTypeInfo->placementSize)) 2948 pPgpuInfo->creatablePlacementIds[i][j] = pVgpuTypeInfo->supportedPlacementIds[j]; 2949 } 2950 2951 if (pPgpuInfo->creatablePlacementIds[i][j] != NVA081_PLACEMENT_ID_INVALID) 2952 isVgpuTypeCreatable = NV_TRUE; 2953 } 2954 2955 if (isVgpuTypeCreatable) 2956 pPgpuInfo->supportedTypeIds[numCreatable++] = pVgpuTypeInfo->vgpuTypeId; 2957 } 2958 2959 return NV_OK; 2960 } 2961 2962 NV_STATUS 2963 kvgpumgrUpdateHeterogeneousInfo(OBJGPU *pGpu, NvU32 vgpuTypeId, NvU16 *placementId, 2964 NvU64 *guestFbLength, NvU64 *guestFbOffset, 2965 NvU64 *gspHeapOffset) 2966 { 2967 OBJSYS *pSys = SYS_GET_INSTANCE(); 2968 KernelVgpuMgr *pKernelVgpuMgr = SYS_GET_KERNEL_VGPUMGR(pSys); 2969 KERNEL_PHYS_GPU_INFO *pPgpuInfo; 2970 VGPU_TYPE *pVgpuTypeInfo; 2971 NvU32 index, i , j; 2972 NvBool bIdFound = NV_FALSE; 2973 2974 NV_CHECK_OK_OR_RETURN(LEVEL_ERROR, 2975 kvgpumgrGetPgpuIndex(pKernelVgpuMgr, pGpu->gpuId, &index)); 2976 2977 pPgpuInfo = &(pKernelVgpuMgr->pgpuInfo[index]); 2978 2979 for (i = 0; i < pPgpuInfo->numVgpuTypes; i++) 2980 { 2981 pVgpuTypeInfo = pPgpuInfo->vgpuTypes[i]; 2982 if (pVgpuTypeInfo == NULL) 2983 break; 2984 2985 if (pVgpuTypeInfo->vgpuTypeId == vgpuTypeId) 2986 { 2987 for (j = 0; j < pVgpuTypeInfo->placementCount; j++) 2988 { 2989 /* 2990 * If hypervisor hasn't provided the placement ID as input, look 2991 * for the first available placement ID for the input vGPU type. 2992 * If hypervisor has provided the placement ID as input, just 2993 * validate if it is a creatable placement ID. 2994 */ 2995 if (*placementId == NVA081_PLACEMENT_ID_INVALID) 2996 { 2997 if (pPgpuInfo->creatablePlacementIds[i][j] != NVA081_PLACEMENT_ID_INVALID) 2998 { 2999 *placementId = pPgpuInfo->creatablePlacementIds[i][j]; 3000 *guestFbOffset = pPgpuInfo->supportedVmmuOffsets[i][j] * 3001 gpuGetVmmuSegmentSize(pGpu); 3002 *guestFbLength = pPgpuInfo->guestVmmuCount[i] * 3003 gpuGetVmmuSegmentSize(pGpu); 3004 *gspHeapOffset = pPgpuInfo->gspHeapOffsets[i][j]; 3005 bIdFound = NV_TRUE; 3006 break; 3007 } 3008 } 3009 else 3010 { 3011 if (pPgpuInfo->creatablePlacementIds[i][j] == *placementId) 3012 { 3013 *guestFbOffset = pPgpuInfo->supportedVmmuOffsets[i][j] * 3014 gpuGetVmmuSegmentSize(pGpu); 3015 *guestFbLength = pPgpuInfo->guestVmmuCount[i] * 3016 gpuGetVmmuSegmentSize(pGpu); 3017 *gspHeapOffset = pPgpuInfo->gspHeapOffsets[i][j]; 3018 bIdFound = NV_TRUE; 3019 break; 3020 } 3021 } 3022 } 3023 } 3024 } 3025 3026 /* No creatable placement ID found */ 3027 if (!bIdFound) 3028 return NV_ERR_INVALID_STATE; 3029 3030 return _kvgpumgrUpdateCreatablePlacementIds(pGpu, *placementId, vgpuTypeId, NV_TRUE); 3031 } 3032 3033 NV_STATUS 3034 kvgpumgrGetConfigEventInfoFromDb(NvHandle hClient, 3035 NvHandle hVgpuConfig, 3036 VGPU_CONFIG_EVENT_INFO_NODE **ppVgpuConfigEventInfoNode, 3037 NvU32 pgpuIndex) 3038 { 3039 OBJSYS *pSys = SYS_GET_INSTANCE(); 3040 KernelVgpuMgr *pKernelVgpuMgr = SYS_GET_KERNEL_VGPUMGR(pSys); 3041 VGPU_CONFIG_EVENT_INFO_NODE *pVgpuConfigEventInfoNodeTemp; 3042 3043 if (!ppVgpuConfigEventInfoNode) 3044 { 3045 return NV_ERR_INVALID_ARGUMENT; 3046 } 3047 3048 for (pVgpuConfigEventInfoNodeTemp = listHead(&(pKernelVgpuMgr->pgpuInfo[pgpuIndex].listVgpuConfigEventsHead)); 3049 pVgpuConfigEventInfoNodeTemp != NULL; 3050 pVgpuConfigEventInfoNodeTemp = listNext(&(pKernelVgpuMgr->pgpuInfo[pgpuIndex].listVgpuConfigEventsHead), pVgpuConfigEventInfoNodeTemp)) 3051 { 3052 if ((pVgpuConfigEventInfoNodeTemp->hClient == hClient) && 3053 (pVgpuConfigEventInfoNodeTemp->hVgpuConfig == hVgpuConfig)) 3054 { 3055 *ppVgpuConfigEventInfoNode = pVgpuConfigEventInfoNodeTemp; 3056 return NV_OK; 3057 } 3058 } 3059 3060 *ppVgpuConfigEventInfoNode = NULL; 3061 return NV_ERR_OBJECT_NOT_FOUND; 3062 } 3063 3064 NV_STATUS 3065 kvgpuMgrRestoreSmcExecPart 3066 ( 3067 OBJGPU *pGpu, 3068 KERNEL_HOST_VGPU_DEVICE *pKernelHostVgpuDevice, 3069 KERNEL_MIG_GPU_INSTANCE *pKernelMIGGpuInstance 3070 ) 3071 { 3072 NV_STATUS rmStatus = NV_OK; 3073 NvU32 CIIdx; 3074 NVC637_CTRL_EXEC_PARTITIONS_IMPORT_EXPORT_PARAMS *pExecPartImportParams = NULL; 3075 RM_API *pRmApi = rmapiGetInterface(RMAPI_GPU_LOCK_INTERNAL); 3076 3077 // 3078 // Delete any compute instances which are alive in system. This may delete 3079 // instances existing in system even if they are same as default instance, 3080 // as we are not comparing instances 3081 // 3082 for (CIIdx = 0; CIIdx < NV_ARRAY_ELEMENTS(pKernelMIGGpuInstance->MIGComputeInstance); ++CIIdx) 3083 { 3084 NVC637_CTRL_EXEC_PARTITIONS_DELETE_PARAMS params; 3085 MIG_COMPUTE_INSTANCE *pMIGComputeInstance = 3086 &pKernelMIGGpuInstance->MIGComputeInstance[CIIdx]; 3087 3088 if (!pMIGComputeInstance->bValid) 3089 continue; 3090 3091 portMemSet(¶ms, 0, sizeof(params)); 3092 params.execPartCount = 1; 3093 params.execPartId[0] = CIIdx; 3094 3095 // 3096 // There is no revert or failure in this call as we have to do best case 3097 // effort to delete and restore default compute instances 3098 // 3099 NV_ASSERT_OK( 3100 pRmApi->Control(pRmApi, 3101 pKernelMIGGpuInstance->instanceHandles.hClient, 3102 pKernelMIGGpuInstance->instanceHandles.hSubscription, 3103 NVC637_CTRL_CMD_EXEC_PARTITIONS_DELETE, 3104 ¶ms, 3105 sizeof(params))); 3106 } 3107 3108 // Restore all saved compute instances 3109 pExecPartImportParams = portMemAllocNonPaged(sizeof(*pExecPartImportParams)); 3110 NV_ASSERT_OR_RETURN(pExecPartImportParams != NULL, NV_ERR_NO_MEMORY); 3111 3112 for (CIIdx = 0; CIIdx < NV_ARRAY_ELEMENTS(pKernelMIGGpuInstance->MIGComputeInstance); ++CIIdx) 3113 { 3114 GPUMGR_SAVE_COMPUTE_INSTANCE *pComputeInstanceSave = &pKernelHostVgpuDevice->savedExecPartitions[CIIdx]; 3115 if (!pComputeInstanceSave->bValid) 3116 continue; 3117 3118 portMemSet(pExecPartImportParams, 0, sizeof(*pExecPartImportParams)); 3119 pExecPartImportParams->id = pComputeInstanceSave->id; 3120 pExecPartImportParams->bCreateCap = NV_TRUE; 3121 portMemCopy(&pExecPartImportParams->info, sizeof(pExecPartImportParams->info), 3122 &pComputeInstanceSave->ciInfo, sizeof(pComputeInstanceSave->ciInfo)); 3123 3124 NV_ASSERT_OK_OR_GOTO(rmStatus, 3125 pRmApi->Control(pRmApi, 3126 pKernelMIGGpuInstance->instanceHandles.hClient, 3127 pKernelMIGGpuInstance->instanceHandles.hSubscription, 3128 NVC637_CTRL_CMD_EXEC_PARTITIONS_IMPORT, 3129 pExecPartImportParams, 3130 sizeof(*pExecPartImportParams)), 3131 done); 3132 } 3133 3134 // 3135 // Generate a subdevice event stating something has changed in GPU partition 3136 // config. 3137 // 3138 gpuNotifySubDeviceEvent(pGpu, NV2080_NOTIFIERS_SMC_CONFIG_UPDATE, NULL, 0, 0, 0); 3139 3140 done: 3141 portMemFree(pExecPartImportParams); 3142 return rmStatus; 3143 } 3144