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 static _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 switch (chipID) 1400 { 1401 default: 1402 // The encoding of the subdevice ID is its value converted to string 1403 bytes = NvU32ToAsciiStr(subID, SUBDEVID_ENCODED_VALUE_SIZE, 1404 pgpuString, NV_FALSE); 1405 break; 1406 } 1407 1408 return bytes; 1409 } 1410 1411 NvU32 kvgpumgrGetPgpuFSEncoding(OBJGPU *pGpu, NvU8 *pgpuString, 1412 NvU32 strSize) 1413 { 1414 RM_API *pRmApi = GPU_GET_PHYSICAL_RMAPI(pGpu); 1415 NV2080_CTRL_VGPU_MGR_INTERNAL_GET_PGPU_FS_ENCODING_PARAMS params = {0}; 1416 NV_STATUS status; 1417 1418 params.pgpuStringSize = strSize; 1419 1420 NV_CHECK_OK_OR_ELSE(status, 1421 LEVEL_ERROR, 1422 pRmApi->Control(pRmApi, pGpu->hInternalClient, pGpu->hInternalSubdevice, 1423 NV2080_CTRL_CMD_VGPU_MGR_INTERNAL_GET_PGPU_FS_ENCODING, 1424 ¶ms, sizeof(params)), 1425 return NV_U32_MAX); 1426 1427 portMemCopy(pgpuString, strSize, params.pgpuString, params.pgpuStringSize); 1428 1429 return params.pgpuStringSize; 1430 } 1431 1432 NvU64 1433 kvgpumgrGetEccAndPrReservedFb(OBJGPU *pGpu) 1434 { 1435 Heap *pHeap = GPU_GET_HEAP(pGpu); 1436 const MEMORY_SYSTEM_STATIC_CONFIG *pMemorySystemConfig = 1437 kmemsysGetStaticConfig(pGpu, GPU_GET_KERNEL_MEMORY_SYSTEM(pGpu)); 1438 NvU64 eccReservedFb = 0, pageRetirementReservedFb = 0, usableSizeFb; 1439 1440 // 1441 // pageRetirementReservedFb is needed only in case of legacy, to account 1442 // for the pagepool used during page stitching 1443 // 1444 if (!gpuIsSriovEnabled(pGpu)) 1445 { 1446 if (pGpu->getProperty(pGpu, PDB_PROP_GPU_ALLOW_PAGE_RETIREMENT)) 1447 { 1448 if (IsPASCALorBetter(pGpu)) 1449 { 1450 pageRetirementReservedFb = NV2080_CTRL_FB_OFFLINED_PAGES_MAX_PAGES * RM_PAGE_SIZE_HUGE; 1451 } 1452 else 1453 { 1454 pageRetirementReservedFb = NV2080_CTRL_FB_OFFLINED_PAGES_MAX_PAGES * RM_PAGE_SIZE_64K; 1455 } 1456 } 1457 } 1458 1459 if (pMemorySystemConfig->bEnabledEccFBPA) 1460 { 1461 if ((pMemorySystemConfig->ramType != NV2080_CTRL_FB_INFO_RAM_TYPE_HBM1) && 1462 (pMemorySystemConfig->ramType != NV2080_CTRL_FB_INFO_RAM_TYPE_HBM2) && 1463 (pMemorySystemConfig->ramType != NV2080_CTRL_FB_INFO_RAM_TYPE_HBM3)) 1464 { 1465 heapGetUsableSize(pHeap, &usableSizeFb); 1466 // 1467 // FB and ECC checksum calculation 1468 // eccReservedFb = totalFBEccOff / 16 1469 // i.e. totalFbEccOff = eccReservedFb * 16 1470 // 1471 // totalFbEccOff = totalFbEccOn + eccReservedFb 1472 // eccReservedFb * 16 = totalFbEccOn + eccReservedFb 1473 // eccReservedFb * 15 = totalFbEccOn 1474 // eccReservedFb = totalFbEccOn / 15 (totalFbEccOn is same as usableSizeFb) 1475 // 1476 eccReservedFb = usableSizeFb / 15; 1477 } 1478 } 1479 1480 return pageRetirementReservedFb + eccReservedFb; 1481 } 1482 1483 // 1484 // A 32-bit variable is used to consolidate various GPU capabilities like 1485 // ECC, SRIOV etc. The function sets the capabilities in the variable and 1486 // converted to an ascii-encoded format. 1487 // 1488 NvU32 kvgpumgrGetPgpuCapEncoding(OBJGPU *pGpu, NvU8 *pgpuString, NvU32 strSize) 1489 { 1490 RM_API *pRmApi = GPU_GET_PHYSICAL_RMAPI(pGpu); 1491 NvU32 pgpuCap = 0; 1492 1493 if ((strSize < MAX_NVU32_TO_CONVERTED_STR_LEN) || (pgpuString == NULL)) 1494 { 1495 return NV_U32_MAX; 1496 } 1497 1498 { 1499 NV2080_CTRL_GPU_QUERY_ECC_STATUS_PARAMS eccStatus = {0}; 1500 1501 if (pRmApi->Control(pRmApi, 1502 pGpu->hInternalClient, 1503 pGpu->hInternalSubdevice, 1504 NV2080_CTRL_CMD_GPU_QUERY_ECC_STATUS, 1505 &eccStatus, sizeof(eccStatus)) == NV_OK) 1506 { 1507 NvU32 i; 1508 for (i = 0; i < NV2080_CTRL_GPU_ECC_UNIT_COUNT; i++) 1509 { 1510 if (eccStatus.units[i].enabled) 1511 { 1512 pgpuCap |= PGPU_CAP_ECC_ON; 1513 break; 1514 } 1515 } 1516 } 1517 } 1518 1519 { 1520 NV0080_CTRL_GPU_GET_SRIOV_CAPS_PARAMS sriovCaps = {0}; 1521 1522 if (gpuGetSriovCaps_HAL(pGpu, &sriovCaps) == NV_OK) 1523 { 1524 if (sriovCaps.bSriovEnabled) 1525 pgpuCap |= PGPU_CAP_SRIOV_ON; 1526 } 1527 } 1528 1529 return NvU32ToAsciiStr(pgpuCap, PGPU_CAP_ENCODED_VALUE_SIZE, 1530 pgpuString, NV_FALSE); 1531 } 1532 1533 /* 1534 * Get the user provide vGPU version range 1535 */ 1536 NV_STATUS 1537 kvgpumgrGetHostVgpuVersion(NvU32 *user_min_supported_version, 1538 NvU32 *user_max_supported_version) 1539 { 1540 OBJSYS *pSys = SYS_GET_INSTANCE(); 1541 KernelVgpuMgr *pKernelVgpuMgr = SYS_GET_KERNEL_VGPUMGR(pSys); 1542 1543 *user_min_supported_version 1544 = pKernelVgpuMgr->user_min_supported_version; 1545 *user_max_supported_version 1546 = pKernelVgpuMgr->user_max_supported_version; 1547 return NV_OK; 1548 } 1549 1550 /* 1551 * Set the user provide vGPU version range 1552 */ 1553 NV_STATUS 1554 kvgpumgrSetHostVgpuVersion(NvU32 user_min_supported_version, 1555 NvU32 user_max_supported_version) 1556 { 1557 OBJSYS *pSys = SYS_GET_INSTANCE(); 1558 KernelVgpuMgr *pKernelVgpuMgr = SYS_GET_KERNEL_VGPUMGR(pSys); 1559 NvU32 host_min_supported_version 1560 = GRIDSW_VERSION_EXTERNAL(NV_VGPU_MIN_SUPPORTED_GRIDSW_VERSION_EXTERNAL_MAJOR, 1561 NV_VGPU_MIN_SUPPORTED_GRIDSW_VERSION_EXTERNAL_MINOR); 1562 NvU32 host_max_supported_version 1563 = GRIDSW_VERSION_EXTERNAL(NV_VGPU_MAX_SUPPORTED_GRIDSW_VERSION_EXTERNAL_MAJOR, 1564 NV_VGPU_MAX_SUPPORTED_GRIDSW_VERSION_EXTERNAL_MINOR); 1565 1566 /* Sanity check */ 1567 if (user_min_supported_version > user_max_supported_version) { 1568 NV_PRINTF(LEVEL_ERROR, 1569 "Maximum vGPU version (0x%x) being set is less than minimum version (0x%x)\n", 1570 user_max_supported_version, user_min_supported_version); 1571 return NV_ERR_INVALID_ARGUMENT; 1572 } 1573 1574 /* Sanity check: Fail in case the range being set by admin is a subset 1575 * of the range supported by the host driver 1576 */ 1577 if ((user_min_supported_version < host_min_supported_version) 1578 || (user_max_supported_version > host_max_supported_version)) { 1579 1580 NV_PRINTF(LEVEL_ERROR, 1581 "vGPU version range being set (0x%x, 0x%x) is outside the range supported by host (0x%x, 0x%x)\n", 1582 user_min_supported_version, user_max_supported_version, 1583 host_min_supported_version, host_max_supported_version); 1584 1585 return NV_ERR_INVALID_ARGUMENT; 1586 } 1587 1588 NV_PRINTF(LEVEL_INFO, 1589 "vGPU version range enforced by user: (0x%x, 0x%x)\n", 1590 user_min_supported_version, user_max_supported_version); 1591 1592 /* Save the information of the user specified range in the host */ 1593 pKernelVgpuMgr->user_min_supported_version 1594 = user_min_supported_version; 1595 pKernelVgpuMgr->user_max_supported_version 1596 = user_max_supported_version; 1597 1598 return NV_OK; 1599 } 1600 1601 /* 1602 * Function to set swizzId is assigned to a vGPU device. 1603 */ 1604 static NV_STATUS 1605 _kvgpumgrSetAssignedSwizzIdMask(OBJGPU *pGpu, 1606 NvU32 swizzId) 1607 { 1608 OBJSYS *pSys = SYS_GET_INSTANCE(); 1609 KernelVgpuMgr *pKernelVgpuMgr = SYS_GET_KERNEL_VGPUMGR(pSys); 1610 KERNEL_PHYS_GPU_INFO *pPhysGpuInfo; 1611 NvU32 i; 1612 NvU64 mask; 1613 1614 if (swizzId >= KMIGMGR_MAX_GPU_SWIZZID) 1615 { 1616 return NV_ERR_INVALID_ARGUMENT; 1617 } 1618 1619 if (kvgpumgrGetPgpuIndex(pKernelVgpuMgr, pGpu->gpuId, &i) != NV_OK) 1620 { 1621 return NV_ERR_OBJECT_NOT_FOUND; 1622 } 1623 1624 pPhysGpuInfo = &(pKernelVgpuMgr->pgpuInfo[i]); 1625 NV_ASSERT_OR_RETURN((pPhysGpuInfo != NULL), NV_ERR_INVALID_ARGUMENT); 1626 1627 /* Validate that same ID is not already set and then set the ID */ 1628 mask = NVBIT64(swizzId); 1629 1630 if (mask & pPhysGpuInfo->assignedSwizzIdMask) 1631 { 1632 NV_PRINTF(LEVEL_ERROR, "SwizzID - %d already in use\n", swizzId); 1633 DBG_BREAKPOINT(); 1634 return NV_ERR_STATE_IN_USE; 1635 } 1636 1637 pPhysGpuInfo->assignedSwizzIdMask |= mask; 1638 1639 return NV_OK; 1640 } 1641 1642 /*! 1643 * Function to mark swizzId is free to be used by other vGPU devices. 1644 */ 1645 static NV_STATUS 1646 _kvgpumgrClearAssignedSwizzIdMask(OBJGPU *pGpu, 1647 NvU32 swizzId) 1648 { 1649 OBJSYS *pSys = SYS_GET_INSTANCE(); 1650 KernelVgpuMgr *pKernelVgpuMgr = SYS_GET_KERNEL_VGPUMGR(pSys); 1651 KERNEL_PHYS_GPU_INFO *pPhysGpuInfo; 1652 NvU32 i; 1653 NvU64 mask; 1654 1655 if (swizzId >= KMIGMGR_MAX_GPU_SWIZZID) 1656 { 1657 return NV_ERR_INVALID_ARGUMENT; 1658 } 1659 1660 if (kvgpumgrGetPgpuIndex(pKernelVgpuMgr, pGpu->gpuId, &i) != NV_OK) 1661 { 1662 return NV_ERR_OBJECT_NOT_FOUND; 1663 } 1664 1665 pPhysGpuInfo = &(pKernelVgpuMgr->pgpuInfo[i]); 1666 NV_ASSERT_OR_RETURN((pPhysGpuInfo != NULL), NV_ERR_INVALID_ARGUMENT); 1667 1668 /* Validate that same ID is not already marked as free and then set the ID */ 1669 mask = NVBIT64(swizzId); 1670 1671 if (!(mask & pPhysGpuInfo->assignedSwizzIdMask)) 1672 { 1673 NV_PRINTF(LEVEL_ERROR, "SwizzID - %d not in use\n", swizzId); 1674 DBG_BREAKPOINT(); 1675 return NV_ERR_INVALID_STATE; 1676 } 1677 1678 pPhysGpuInfo->assignedSwizzIdMask &= ~mask; 1679 1680 return NV_OK; 1681 } 1682 1683 NV_STATUS 1684 kvgpumgrGetSwizzId(OBJGPU *pGpu, 1685 KERNEL_PHYS_GPU_INFO *pPhysGpuInfo, 1686 NvU32 partitionFlag, 1687 NvU32 *swizzId) 1688 { 1689 KernelMIGManager *pKernelMIGManager = GPU_GET_KERNEL_MIG_MANAGER(pGpu); 1690 NvU64 swizzIdInUseMask = 0; 1691 NvU32 id; 1692 NV_STATUS rmStatus = NV_OK; 1693 1694 swizzIdInUseMask = kmigmgrGetSwizzIdInUseMask(pGpu, pKernelMIGManager); 1695 1696 *swizzId = KMIGMGR_SWIZZID_INVALID; 1697 1698 // Determine valid swizzids not assigned to any vGPU device. 1699 FOR_EACH_INDEX_IN_MASK(64, id, swizzIdInUseMask) 1700 { 1701 KERNEL_MIG_GPU_INSTANCE *pKernelMIGGpuInstance; 1702 NvU64 mask = 0; 1703 1704 rmStatus = kmigmgrGetGPUInstanceInfo(pGpu, pKernelMIGManager, id, &pKernelMIGGpuInstance); 1705 if (rmStatus != NV_OK) 1706 { 1707 // Didn't find requested GPU instance 1708 NV_PRINTF(LEVEL_ERROR, "No valid GPU instance with SwizzId - %d found\n", id); 1709 return rmStatus; 1710 } 1711 1712 mask = NVBIT64(id); 1713 1714 if (pKernelMIGGpuInstance->partitionFlag == partitionFlag) 1715 { 1716 // Validate that same ID is not already set and then set the ID 1717 if (!(mask & pPhysGpuInfo->assignedSwizzIdMask)) 1718 { 1719 NV_ASSERT_OK_OR_RETURN(_kvgpumgrSetAssignedSwizzIdMask(pGpu, pKernelMIGGpuInstance->swizzId)); 1720 *swizzId = pKernelMIGGpuInstance->swizzId; 1721 break; 1722 } 1723 } 1724 } 1725 FOR_EACH_INDEX_IN_MASK_END; 1726 1727 if (*swizzId == KMIGMGR_SWIZZID_INVALID) 1728 { 1729 return NV_ERR_INVALID_STATE; 1730 } 1731 1732 return NV_OK; 1733 } 1734 1735 NV_STATUS 1736 kvgpumgrValidateSwizzId(OBJGPU *pGpu, 1737 NvU32 vgpuTypeId, 1738 NvU32 swizzId) 1739 { 1740 KernelMIGManager *pKernelMIGManager = GPU_GET_KERNEL_MIG_MANAGER(pGpu); 1741 NvU32 partitionFlag = PARTITIONID_INVALID; 1742 NV_STATUS rmStatus = NV_OK; 1743 KERNEL_MIG_GPU_INSTANCE *pKernelMIGGpuInstance; 1744 1745 // Check if swizzId is valid. 1746 if (!kmigmgrIsSwizzIdInUse(pGpu, pKernelMIGManager, swizzId)) 1747 { 1748 return NV_ERR_INVALID_ARGUMENT; 1749 } 1750 1751 rmStatus = kmigmgrGetGPUInstanceInfo(pGpu, pKernelMIGManager, swizzId, &pKernelMIGGpuInstance); 1752 if (rmStatus != NV_OK) 1753 { 1754 // Didn't find requested GPU instance 1755 NV_PRINTF(LEVEL_ERROR, "No valid GPU instance with SwizzId - %d found\n", swizzId); 1756 return rmStatus; 1757 } 1758 1759 NV_ASSERT_OK_OR_RETURN( 1760 kvgpumgrGetPartitionFlag(vgpuTypeId, &partitionFlag)); 1761 1762 // Check if swizzId is valid for vGPU type. 1763 if (pKernelMIGGpuInstance->partitionFlag == partitionFlag) 1764 { 1765 NV_ASSERT_OK_OR_RETURN(_kvgpumgrSetAssignedSwizzIdMask(pGpu, swizzId)); 1766 return NV_OK; 1767 } 1768 1769 return NV_ERR_INVALID_STATE; 1770 } 1771 1772 NV_STATUS 1773 kvgpumgrGetPartitionFlag(NvU32 vgpuTypeId, NvU32 *partitionFlag) 1774 { 1775 NvU32 i; 1776 1777 *partitionFlag = PARTITIONID_INVALID; 1778 1779 for (i = 0; i < NV_ARRAY_ELEMENTS(vgpuSmcTypeIdMappings); i++) 1780 { 1781 if (vgpuSmcTypeIdMappings[i].vgpuTypeId == vgpuTypeId) 1782 { 1783 *partitionFlag = vgpuSmcTypeIdMappings[i].partitionFlag; 1784 return NV_OK; 1785 } 1786 } 1787 1788 NV_PRINTF(LEVEL_ERROR, "Invalid SMC vGpu TypeId: 0x%x\n", vgpuTypeId); 1789 return NV_ERR_INVALID_ARGUMENT; 1790 } 1791 1792 static NV_STATUS 1793 _kvgpumgrGetVgpuTypeIdFromPartitionFlag(NvU32 devId, NvU32 partitionFlag, NvU32 *vgpuTypeId) 1794 { 1795 NvU32 i; 1796 1797 *vgpuTypeId = NVA081_CTRL_VGPU_CONFIG_INVALID_TYPE; 1798 1799 for (i = 0; i < NV_ARRAY_ELEMENTS(vgpuSmcTypeIdMappings); i++) 1800 { 1801 // Currently vgpuTypeId to partitionFlag mapping is 1 to 1. 1802 // In future, we might potentially hit issue if multiple 1803 // type-ids map to the same partition flags 1804 if ((vgpuSmcTypeIdMappings[i].devId == devId) && 1805 (vgpuSmcTypeIdMappings[i].partitionFlag == partitionFlag)) 1806 { 1807 *vgpuTypeId = vgpuSmcTypeIdMappings[i].vgpuTypeId; 1808 return NV_OK; 1809 } 1810 } 1811 1812 return NV_ERR_OBJECT_NOT_FOUND; 1813 } 1814 1815 /* 1816 * Add or remove VF info to pgpuInfo of its PF 1817 * @param[in] gpuPciId PCI ID of target PF 1818 * @param[in] cmd 1819 * 0/VGPU_CMD_PROCESS_VF_INFO.NV_VGPU_SAVE_VF_INFO = Add VF info to VF list of target PF 1820 * 1/VGPU_CMD_PROCESS_VF_INFO.NV_VGPU_REMOVE_VF_INFO = Remove VF info from VF list of target PF 1821 * @param[in] domain Domain of VF to be stored 1822 * @param[in] bus Bus no. of VF to be stored 1823 * @param[in] slot Slot no. of VF to be stored 1824 * @param[in] function Function of VF to be stored 1825 * @param[in] isMdevAttached Flag to indicate if VF is registered with mdev 1826 * @param[out]vfPciInfo Array of PCI information of VFs 1827 */ 1828 NV_STATUS 1829 kvgpumgrProcessVfInfo(NvU32 gpuPciId, NvU8 cmd, NvU32 domain, NvU32 bus, NvU32 slot, NvU32 function, NvBool isMdevAttached, vgpu_vf_pci_info *vfPciInfo) 1830 { 1831 NvU32 i; 1832 OBJSYS *pSys = SYS_GET_INSTANCE(); 1833 KernelVgpuMgr *pKernelVgpuMgr = SYS_GET_KERNEL_VGPUMGR(pSys); 1834 NvU32 pgpuIndex; 1835 NV_STATUS status = NV_OK; 1836 KERNEL_PHYS_GPU_INFO *pPhysGpuInfo; 1837 vgpu_vf_pci_info *pVfInfo = NULL; 1838 1839 if ((status = kvgpumgrGetPgpuIndex(pKernelVgpuMgr, gpuPciId, &pgpuIndex)) != NV_OK) 1840 return status; 1841 1842 pPhysGpuInfo = &(pKernelVgpuMgr->pgpuInfo[pgpuIndex]); 1843 1844 if (cmd == NV_VGPU_SAVE_VF_INFO) 1845 { 1846 /* Find existing entry for VF and set flags if found. */ 1847 for (i = 0; i < MAX_VF_COUNT_PER_GPU; i++) 1848 { 1849 pVfInfo = &pPhysGpuInfo->vfPciInfo[i]; 1850 1851 if ((domain == pVfInfo->domain) && 1852 (bus == pVfInfo->bus) && 1853 (slot == pVfInfo->slot) && 1854 (function == pVfInfo->function)) 1855 { 1856 pVfInfo->isNvidiaAttached = NV_TRUE; 1857 pVfInfo->isMdevAttached = isMdevAttached; 1858 break; 1859 } 1860 } 1861 1862 /* 1863 * If entry doesn't already exist, populate an empty slot and complain 1864 * if there isn't one. 1865 */ 1866 if (i == MAX_VF_COUNT_PER_GPU) 1867 { 1868 for (i = 0; i < MAX_VF_COUNT_PER_GPU; i++) 1869 { 1870 pVfInfo = &pPhysGpuInfo->vfPciInfo[i]; 1871 if ((!pVfInfo->isNvidiaAttached)) 1872 { 1873 pVfInfo->domain = domain; 1874 pVfInfo->bus = bus; 1875 pVfInfo->slot = slot; 1876 pVfInfo->function = function; 1877 1878 pVfInfo->isNvidiaAttached = NV_TRUE; 1879 pVfInfo->isMdevAttached = isMdevAttached; 1880 break; 1881 } 1882 } 1883 1884 if (i == MAX_VF_COUNT_PER_GPU) 1885 { 1886 NV_PRINTF(LEVEL_ERROR, "No free free slot to track VF PCI info\n"); 1887 return NV_ERR_INVALID_STATE; 1888 } 1889 } 1890 } 1891 else if ((cmd == NV_VGPU_REMOVE_VF_PCI_INFO || cmd == NV_VGPU_REMOVE_VF_MDEV_INFO) && pPhysGpuInfo) 1892 { 1893 for (i = 0; i < MAX_VF_COUNT_PER_GPU; i++) 1894 { 1895 pVfInfo = &pPhysGpuInfo->vfPciInfo[i]; 1896 1897 if ((domain == pVfInfo->domain) && 1898 (bus == pVfInfo->bus) && 1899 (slot == pVfInfo->slot) && 1900 (function == pVfInfo->function)) 1901 { 1902 if (cmd == NV_VGPU_REMOVE_VF_PCI_INFO) 1903 { 1904 pVfInfo->isNvidiaAttached = NV_FALSE; 1905 } 1906 pVfInfo->isMdevAttached = NV_FALSE; 1907 break; 1908 } 1909 } 1910 1911 if (i == MAX_VF_COUNT_PER_GPU) 1912 { 1913 NV_PRINTF(LEVEL_ERROR, "Could not find entry for VF PCI info\n"); 1914 return NV_ERR_MISSING_TABLE_ENTRY; 1915 } 1916 } 1917 else if (cmd == NV_VGPU_GET_VF_INFO && vfPciInfo) 1918 { 1919 for (i = 0; i < MAX_VF_COUNT_PER_GPU; i++) 1920 { 1921 pVfInfo = &pPhysGpuInfo->vfPciInfo[i]; 1922 portMemCopy(&vfPciInfo[i], sizeof(vgpu_vf_pci_info), pVfInfo, sizeof(vgpu_vf_pci_info)); 1923 } 1924 } 1925 else 1926 { 1927 NV_PRINTF(LEVEL_ERROR, "Requested invalid operation on VF info\n"); 1928 status = NV_ERR_INVALID_ARGUMENT; 1929 } 1930 1931 return status; 1932 } 1933 1934 NV_STATUS 1935 kvgpumgrEnumerateVgpuPerPgpu(OBJGPU *pGpu, NV2080_CTRL_VGPU_MGR_INTERNAL_ENUMERATE_VGPU_PER_PGPU_PARAMS *pParams) 1936 { 1937 RM_API *pRmApi = GPU_GET_PHYSICAL_RMAPI(pGpu); 1938 1939 NV_CHECK_OK_OR_RETURN(LEVEL_ERROR, pRmApi->Control(pRmApi, pGpu->hInternalClient, pGpu->hInternalSubdevice, 1940 NV2080_CTRL_CMD_VGPU_MGR_INTERNAL_ENUMERATE_VGPU_PER_PGPU, 1941 pParams, sizeof(*pParams))); 1942 1943 return NV_OK; 1944 } 1945 1946 NV_STATUS 1947 kvgpumgrClearGuestVmInfo(OBJGPU *pGpu, KERNEL_HOST_VGPU_DEVICE *pKernelHostVgpuDevice) 1948 { 1949 NV2080_CTRL_VGPU_MGR_INTERNAL_CLEAR_GUEST_VM_INFO_PARAMS params; 1950 RM_API *pRmApi = GPU_GET_PHYSICAL_RMAPI(pGpu); 1951 NV_STATUS status; 1952 1953 portMemSet(¶ms, 0, sizeof(params)); 1954 params.gfid = pKernelHostVgpuDevice->gfid; 1955 1956 status = pRmApi->Control(pRmApi, pGpu->hInternalClient, pGpu->hInternalSubdevice, 1957 NV2080_CTRL_CMD_VGPU_MGR_INTERNAL_CLEAR_GUEST_VM_INFO, 1958 ¶ms, sizeof(params)); 1959 1960 if (status != NV_OK) 1961 NV_PRINTF(LEVEL_ERROR, "Failed to clear guest vm info on GSP\n"); 1962 1963 return status; 1964 } 1965 1966 NV_STATUS 1967 kvgpumgrGetHostVgpuDeviceFromGfid(NvU32 gpuPciId, NvU32 gfid, 1968 KERNEL_HOST_VGPU_DEVICE** ppHostVgpuDevice) 1969 { 1970 OBJSYS *pSys = SYS_GET_INSTANCE(); 1971 KernelVgpuMgr *pKernelVgpuMgr = SYS_GET_KERNEL_VGPUMGR(pSys); 1972 NvU32 pgpuIndex; 1973 KERNEL_PHYS_GPU_INFO *pPgpuInfo; 1974 KERNEL_HOST_VGPU_DEVICE *pKernelHostVgpuDevice; 1975 1976 NV_CHECK_OK_OR_RETURN(LEVEL_ERROR, kvgpumgrGetPgpuIndex(pKernelVgpuMgr, gpuPciId, &pgpuIndex)); 1977 pPgpuInfo = &pKernelVgpuMgr->pgpuInfo[pgpuIndex]; 1978 1979 if (!pPgpuInfo->sriovEnabled) 1980 return NV_ERR_NOT_SUPPORTED; 1981 1982 for (pKernelHostVgpuDevice = listHead(&(pPgpuInfo->listHostVgpuDeviceHead)); 1983 pKernelHostVgpuDevice != NULL; 1984 pKernelHostVgpuDevice = listNext(&(pPgpuInfo->listHostVgpuDeviceHead), pKernelHostVgpuDevice)) 1985 { 1986 if (pKernelHostVgpuDevice->gfid == gfid) 1987 { 1988 *ppHostVgpuDevice = pKernelHostVgpuDevice; 1989 return NV_OK; 1990 } 1991 } 1992 1993 return NV_ERR_OBJECT_NOT_FOUND; 1994 } 1995 1996 NV_STATUS 1997 kvgpumgrGetVgpuFbUsage(OBJGPU *pGpu, NVA081_CTRL_VGPU_CONFIG_GET_VGPU_FB_USAGE_PARAMS *pParams) 1998 { 1999 KERNEL_HOST_VGPU_DEVICE *pKernelHostVgpuDevice; 2000 NVA081_VGPU_FB_USAGE *pVgpuFbUsage; 2001 NvU32 i = 0; 2002 2003 NV_PRINTF(LEVEL_INFO, "%s\n", __FUNCTION__); 2004 2005 if (gpuIsSriovEnabled(pGpu)) 2006 { 2007 NV2080_CTRL_VGPU_MGR_INTERNAL_GET_VGPU_FB_USAGE_PARAMS internalParams; 2008 RM_API *pRmApi = GPU_GET_PHYSICAL_RMAPI(pGpu); 2009 2010 portMemSet(&internalParams, 0, sizeof(internalParams)); 2011 2012 NV_CHECK_OK_OR_RETURN(LEVEL_ERROR, pRmApi->Control(pRmApi, pGpu->hInternalClient, pGpu->hInternalSubdevice, 2013 NV2080_CTRL_CMD_VGPU_MGR_INTERNAL_GET_VGPU_FB_USAGE, 2014 &internalParams, sizeof(internalParams))); 2015 2016 if (internalParams.vgpuCount > NV_ARRAY_ELEMENTS(pParams->vgpuFbUsage)) 2017 return NV_ERR_INSUFFICIENT_RESOURCES; 2018 2019 for (i = 0; i < internalParams.vgpuCount; i++) 2020 { 2021 NV_CHECK_OK_OR_RETURN(LEVEL_ERROR, 2022 kvgpumgrGetHostVgpuDeviceFromGfid(pGpu->gpuId, internalParams.vgpuFbUsage[i].gfid, &pKernelHostVgpuDevice)); 2023 2024 pVgpuFbUsage = &pParams->vgpuFbUsage[i]; 2025 2026 portMemCopy(pVgpuFbUsage->vgpuUuid, VGPU_UUID_SIZE, pKernelHostVgpuDevice->vgpuUuid, VGPU_UUID_SIZE); 2027 2028 pVgpuFbUsage->fbUsed = internalParams.vgpuFbUsage[i].fbUsed; 2029 } 2030 2031 pParams->vgpuCount = internalParams.vgpuCount; 2032 } 2033 2034 return NV_OK; 2035 } 2036 2037 NV_STATUS 2038 kvgpumgrSetVgpuEncoderCapacity(OBJGPU *pGpu, NvU8 *vgpuUuid, NvU32 encoderCapacity) 2039 { 2040 OBJSYS *pSys = SYS_GET_INSTANCE(); 2041 KernelVgpuMgr *pKernelVgpuMgr = SYS_GET_KERNEL_VGPUMGR(pSys); 2042 KERNEL_HOST_VGPU_DEVICE *pKernelHostVgpuDevice; 2043 KERNEL_PHYS_GPU_INFO *pPhysGpuInfo; 2044 NvU32 i; 2045 2046 NV_PRINTF(LEVEL_INFO, "%s\n", __FUNCTION__); 2047 2048 NV_CHECK_OK_OR_RETURN(LEVEL_ERROR, kvgpumgrGetPgpuIndex(pKernelVgpuMgr, pGpu->gpuId, &i)); 2049 2050 pPhysGpuInfo = &pKernelVgpuMgr->pgpuInfo[i]; 2051 2052 for (pKernelHostVgpuDevice = listHead(&(pPhysGpuInfo->listHostVgpuDeviceHead)); 2053 pKernelHostVgpuDevice != NULL; 2054 pKernelHostVgpuDevice = listNext(&(pPhysGpuInfo->listHostVgpuDeviceHead), pKernelHostVgpuDevice)) 2055 { 2056 if (portMemCmp(pKernelHostVgpuDevice->vgpuUuid, vgpuUuid, VGPU_UUID_SIZE) == 0) 2057 break; 2058 } 2059 2060 if (pKernelHostVgpuDevice == NULL) 2061 return NV_ERR_OBJECT_NOT_FOUND; 2062 2063 if (gpuIsSriovEnabled(pGpu)) 2064 { 2065 NV2080_CTRL_VGPU_MGR_INTERNAL_SET_VGPU_ENCODER_CAPACITY_PARAMS params; 2066 RM_API *pRmApi = GPU_GET_PHYSICAL_RMAPI(pGpu); 2067 2068 params.gfid = pKernelHostVgpuDevice->gfid; 2069 params.encoderCapacity = encoderCapacity; 2070 2071 NV_CHECK_OK_OR_RETURN(LEVEL_ERROR, 2072 pRmApi->Control(pRmApi, pGpu->hInternalClient, pGpu->hInternalSubdevice, 2073 NV2080_CTRL_CMD_VGPU_MGR_INTERNAL_SET_VGPU_ENCODER_CAPACITY, 2074 ¶ms, sizeof(params))); 2075 } 2076 2077 return NV_OK; 2078 } 2079 2080 NV_STATUS 2081 kvgpumgrStart(const NvU8 *pMdevUuid, void *waitQueue, NvS32 *returnStatus, 2082 NvU8 *vmName, NvU32 qemuPid) 2083 { 2084 OBJSYS *pSys = SYS_GET_INSTANCE(); 2085 KernelVgpuMgr *pKernelVgpuMgr = SYS_GET_KERNEL_VGPUMGR(pSys); 2086 REQUEST_VGPU_INFO_NODE *pRequestVgpu = NULL; 2087 2088 for (pRequestVgpu = listHead(&(pKernelVgpuMgr->listRequestVgpuHead)); 2089 pRequestVgpu != NULL; 2090 pRequestVgpu = listNext(&(pKernelVgpuMgr->listRequestVgpuHead), pRequestVgpu)) 2091 { 2092 if (portMemCmp(pMdevUuid, pRequestVgpu->mdevUuid, VGPU_UUID_SIZE) == 0) 2093 { 2094 pRequestVgpu->waitQueue = waitQueue; 2095 pRequestVgpu->returnStatus = returnStatus; 2096 pRequestVgpu->vmName = vmName; 2097 pRequestVgpu->qemuPid = qemuPid; 2098 2099 CliAddSystemEvent(NV0000_NOTIFIERS_VM_START, 0); 2100 return NV_OK; 2101 } 2102 } 2103 return NV_ERR_OBJECT_NOT_FOUND; 2104 } 2105 2106 // 2107 // Add vGPU info received on mdev_create sysfs call to REQUEST_VGPU_INFO_NODE 2108 // list. REQUEST_VGPU_INFO_NODE is currently used only for vGPU on KVM. 2109 // 2110 // This funtion first checks whether the vGPU type is supported or not as 2111 // only homegeneous vGPU types are supported currently. Also, this function 2112 // only creates REQUEST_VGPU_INFO_NODE entry, actual vGPU will be created later 2113 // 2114 NV_STATUS 2115 kvgpumgrCreateRequestVgpu(NvU32 gpuPciId, const NvU8 *pMdevUuid, 2116 NvU32 vgpuTypeId, NvU16 *vgpuId, NvU32 gpuPciBdf) 2117 { 2118 OBJSYS *pSys = SYS_GET_INSTANCE(); 2119 OBJGPU *pGpu = gpumgrGetGpuFromId(gpuPciId); 2120 KernelVgpuMgr *pKernelVgpuMgr = SYS_GET_KERNEL_VGPUMGR(pSys); 2121 OBJHYPERVISOR *pHypervisor = SYS_GET_HYPERVISOR(pSys); 2122 NvU32 pgpuIndex; 2123 NV_STATUS status = NV_OK; 2124 VGPU_TYPE *vgpuTypeInfo; 2125 KERNEL_PHYS_GPU_INFO *pPhysGpuInfo; 2126 REQUEST_VGPU_INFO_NODE *pRequestVgpu = NULL; 2127 NvU32 allocFlags = NVOS32_ALLOC_FLAGS_FORCE_MEM_GROWS_UP; 2128 NvU64 vgpuIdSize = 1, tmpVgpuId; 2129 NvU8 devfn = gpuDecodeDevice(gpuPciBdf); 2130 NvU32 swizzId = KMIGMGR_SWIZZID_INVALID; 2131 2132 if (pGpu == NULL) 2133 { 2134 NV_PRINTF(LEVEL_ERROR, "GPU handle is not valid \n"); 2135 return NV_ERR_INVALID_STATE; 2136 } 2137 2138 if ((status = kvgpumgrGetPgpuIndex(pKernelVgpuMgr, gpuPciId, &pgpuIndex)) != NV_OK) 2139 return status; 2140 2141 pPhysGpuInfo = &(pKernelVgpuMgr->pgpuInfo[pgpuIndex]); 2142 2143 if ((status = kvgpumgrGetVgpuTypeInfo(vgpuTypeId, &vgpuTypeInfo)) != NV_OK) 2144 return status; 2145 2146 /* 2147 * For DriverVM, we will defer the createdVfMask validation later 2148 * during open call when the params provided. 2149 * 2150 */ 2151 2152 if (gpuIsSriovEnabled(pGpu) && 2153 !(pHypervisor->getProperty(pHypervisor, PDB_PROP_HYPERVISOR_DRIVERVM_ENABLED))) 2154 { 2155 NvU8 fnId = devfn - pGpu->sriovState.firstVFOffset; 2156 2157 NV_ASSERT_OR_RETURN((fnId < 64), NV_ERR_INVALID_ARGUMENT); 2158 2159 if (pPhysGpuInfo->createdVfMask & NVBIT64(fnId)) 2160 /* mdev device is already created on VF */ 2161 return NV_ERR_INVALID_OPERATION; 2162 } 2163 2164 if (IS_MIG_ENABLED(pGpu)) 2165 { 2166 NvU32 partitionFlag = PARTITIONID_INVALID; 2167 2168 NV_CHECK_OR_RETURN(LEVEL_INFO, 2169 IS_MIG_IN_USE(pGpu), 2170 NV_ERR_INVALID_OPERATION); 2171 2172 NV_ASSERT_OK_OR_RETURN( 2173 kvgpumgrGetPartitionFlag(vgpuTypeInfo->vgpuTypeId, &partitionFlag)); 2174 2175 NV_ASSERT_OK_OR_RETURN( 2176 kvgpumgrGetSwizzId(pGpu, pPhysGpuInfo, partitionFlag, &swizzId)); 2177 } 2178 else 2179 { 2180 // Creation request for a MIG vgpuType 2181 if (vgpuTypeInfo->gpuInstanceSize) 2182 return NV_ERR_INVALID_OPERATION; 2183 2184 status = kvgpumgrCheckVgpuTypeCreatable(pGpu, pPhysGpuInfo, vgpuTypeInfo); 2185 2186 if (status != NV_OK) 2187 return status; 2188 } 2189 2190 /* Initialize heap on first vGPU device creation */ 2191 if (pKernelVgpuMgr->pHeap == NULL) 2192 { 2193 NvU64 tmpSize; 2194 pKernelVgpuMgr->pHeap = portMemAllocNonPaged(sizeof(OBJEHEAP)); 2195 if (pKernelVgpuMgr->pHeap == NULL) 2196 { 2197 status = NV_ERR_NO_MEMORY; 2198 goto failed; 2199 } 2200 2201 constructObjEHeap(pKernelVgpuMgr->pHeap, 1, 0xFFFF + 1, 0, 0); 2202 2203 /* Verify if pHeap is allocated with required size */ 2204 pKernelVgpuMgr->pHeap->eheapGetSize(pKernelVgpuMgr->pHeap, &tmpSize); 2205 if (tmpSize != 0xFFFF) 2206 { 2207 pKernelVgpuMgr->pHeap->eheapDestruct(pKernelVgpuMgr->pHeap); 2208 portMemFree(pKernelVgpuMgr->pHeap); 2209 pKernelVgpuMgr->pHeap = NULL; 2210 status = NV_ERR_INSUFFICIENT_RESOURCES; 2211 goto failed; 2212 } 2213 } 2214 2215 status = pKernelVgpuMgr->pHeap->eheapAlloc(pKernelVgpuMgr->pHeap, 0xdeadbeef, &allocFlags, 2216 &tmpVgpuId, &vgpuIdSize, 1, 1, 2217 NULL, NULL, NULL); 2218 if (status != NV_OK) 2219 { 2220 NV_PRINTF(LEVEL_WARNING, 2221 "Failed to allocate heap for vGPU ID 0x%x\n", 2222 status); 2223 goto failed; 2224 } 2225 2226 *vgpuId = (NvU16) tmpVgpuId; 2227 pRequestVgpu = listPrependNew(&(pKernelVgpuMgr->listRequestVgpuHead)); 2228 if (pRequestVgpu == NULL) 2229 { 2230 status = NV_ERR_NO_MEMORY; 2231 goto failed; 2232 } 2233 2234 portMemSet(pRequestVgpu, 0, sizeof(REQUEST_VGPU_INFO_NODE)); 2235 2236 portMemCopy(pRequestVgpu->mdevUuid, VGPU_UUID_SIZE, pMdevUuid, VGPU_UUID_SIZE); 2237 pRequestVgpu->gpuPciId = gpuPciId; /* For SRIOV, this is PF's gpuPciId */ 2238 pRequestVgpu->vgpuId = *vgpuId; 2239 pRequestVgpu->gpuPciBdf = gpuPciBdf; /* For SRIOV, this is VF's gpuPciBdf */ 2240 2241 if (IS_MIG_IN_USE(pGpu)) 2242 { 2243 pRequestVgpu->swizzId = swizzId; 2244 } 2245 2246 _kvgpumgrSetVgpuType(pGpu, pPhysGpuInfo, vgpuTypeId); 2247 pPhysGpuInfo->numCreatedVgpu++; 2248 2249 if (gpuGetDevice(pGpu) != devfn) /* SRIOV - VF */ 2250 pPhysGpuInfo->createdVfMask |= NVBIT64(devfn - pGpu->sriovState.firstVFOffset); 2251 2252 return NV_OK; 2253 2254 failed: 2255 if (swizzId != KMIGMGR_SWIZZID_INVALID) 2256 _kvgpumgrClearAssignedSwizzIdMask(pGpu, swizzId); 2257 2258 return status; 2259 } 2260 2261 // 2262 // Delete REQUEST_VGPU_INFO_NODE structure from list. 2263 // REQUEST_VGPU_INFO_NODE is currently used only for vGPU on KVM. 2264 // 2265 NV_STATUS 2266 kvgpumgrDeleteRequestVgpu(const NvU8 *pMdevUuid, NvU16 vgpuId) 2267 { 2268 OBJSYS *pSys = SYS_GET_INSTANCE(); 2269 OBJGPU *pGpu = NULL; 2270 NV_STATUS status; 2271 NvU32 pgpuIndex; 2272 KernelVgpuMgr *pKernelVgpuMgr = SYS_GET_KERNEL_VGPUMGR(pSys); 2273 REQUEST_VGPU_INFO_NODE *pRequestVgpu = NULL; 2274 REQUEST_VGPU_INFO_NODE *pRequestVgpuNext = NULL; 2275 NvU8 devfn = 0; 2276 2277 for (pRequestVgpu = listHead(&(pKernelVgpuMgr->listRequestVgpuHead)); 2278 pRequestVgpu != NULL; 2279 pRequestVgpu = pRequestVgpuNext) 2280 { 2281 pRequestVgpuNext = listNext(&(pKernelVgpuMgr->listRequestVgpuHead), pRequestVgpu); 2282 if (portMemCmp(pMdevUuid, pRequestVgpu->mdevUuid, VGPU_UUID_SIZE) == 0) 2283 { 2284 if ((status = kvgpumgrGetPgpuIndex(pKernelVgpuMgr, pRequestVgpu->gpuPciId, 2285 &pgpuIndex)) != NV_OK) 2286 return status; 2287 2288 pGpu = gpumgrGetGpuFromId(pRequestVgpu->gpuPciId); 2289 devfn = gpuDecodeDevice(pRequestVgpu->gpuPciBdf); 2290 2291 pKernelVgpuMgr->pgpuInfo[pgpuIndex].numCreatedVgpu--; 2292 2293 if (pGpu && (gpuGetDevice(pGpu) != devfn)) // SRIOV - VF 2294 pKernelVgpuMgr->pgpuInfo[pgpuIndex].createdVfMask &= ~(NVBIT64(devfn - pGpu->sriovState.firstVFOffset)); 2295 2296 if (IS_MIG_ENABLED(pGpu)) 2297 _kvgpumgrClearAssignedSwizzIdMask(pGpu, pRequestVgpu->swizzId); 2298 else if (pKernelVgpuMgr->pgpuInfo[pgpuIndex].numCreatedVgpu == 0) 2299 _kvgpumgrSetVgpuType(pGpu, &pKernelVgpuMgr->pgpuInfo[pgpuIndex], NVA081_CTRL_VGPU_CONFIG_INVALID_TYPE); 2300 2301 pKernelVgpuMgr->pHeap->eheapFree(pKernelVgpuMgr->pHeap, vgpuId); 2302 2303 listRemove(&(pKernelVgpuMgr->listRequestVgpuHead), pRequestVgpu); 2304 2305 return NV_OK; 2306 } 2307 } 2308 return NV_ERR_OBJECT_NOT_FOUND; 2309 } 2310 2311 NV_STATUS 2312 kvgpumgrGetHostVgpuDeviceFromMdevUuid(NvU32 gpuPciId, const NvU8 *pMdevUuid, 2313 KERNEL_HOST_VGPU_DEVICE **ppKernelHostVgpuDevice) 2314 { 2315 OBJSYS *pSys = SYS_GET_INSTANCE(); 2316 KernelVgpuMgr *pKernelVgpuMgr = SYS_GET_KERNEL_VGPUMGR(pSys); 2317 NvU32 pgpuIndex , rmStatus; 2318 KERNEL_PHYS_GPU_INFO *pPgpuInfo; 2319 KERNEL_HOST_VGPU_DEVICE *pKernelHostVgpuDevice; 2320 2321 if ((rmStatus = kvgpumgrGetPgpuIndex(pKernelVgpuMgr, gpuPciId, &pgpuIndex)) != NV_OK) 2322 return rmStatus; 2323 2324 pPgpuInfo = &pKernelVgpuMgr->pgpuInfo[pgpuIndex]; 2325 2326 for (pKernelHostVgpuDevice = listHead(&(pPgpuInfo->listHostVgpuDeviceHead)); 2327 pKernelHostVgpuDevice != NULL; 2328 pKernelHostVgpuDevice = listNext(&(pPgpuInfo->listHostVgpuDeviceHead), pKernelHostVgpuDevice)) 2329 { 2330 if (pKernelHostVgpuDevice == NULL || pKernelHostVgpuDevice->pRequestVgpuInfoNode == NULL) 2331 return NV_ERR_INVALID_POINTER; 2332 2333 if (portMemCmp(pKernelHostVgpuDevice->pRequestVgpuInfoNode->mdevUuid, 2334 pMdevUuid, VM_UUID_SIZE) == 0) 2335 { 2336 *ppKernelHostVgpuDevice = pKernelHostVgpuDevice; 2337 return NV_OK; 2338 } 2339 } 2340 NV_PRINTF(LEVEL_ERROR, "Object not found\n"); 2341 return NV_ERR_OBJECT_NOT_FOUND; 2342 } 2343 2344 NV_STATUS 2345 kvgpumgrGetHostVgpuDeviceFromVgpuUuid(NvU32 gpuPciId, NvU8 *vgpuUuid, 2346 KERNEL_HOST_VGPU_DEVICE **ppKernelHostVgpuDevice) 2347 { 2348 OBJSYS *pSys = SYS_GET_INSTANCE(); 2349 KernelVgpuMgr *pKernelVgpuMgr = SYS_GET_KERNEL_VGPUMGR(pSys); 2350 NvU32 pgpuIndex; 2351 KERNEL_PHYS_GPU_INFO *pPgpuInfo; 2352 KERNEL_HOST_VGPU_DEVICE *pKernelHostVgpuDevice; 2353 2354 NV_CHECK_OK_OR_RETURN(LEVEL_ERROR, kvgpumgrGetPgpuIndex(pKernelVgpuMgr, gpuPciId, &pgpuIndex)); 2355 2356 pPgpuInfo = &pKernelVgpuMgr->pgpuInfo[pgpuIndex]; 2357 2358 for (pKernelHostVgpuDevice = listHead(&(pPgpuInfo->listHostVgpuDeviceHead)); 2359 pKernelHostVgpuDevice != NULL; 2360 pKernelHostVgpuDevice = listNext(&(pPgpuInfo->listHostVgpuDeviceHead), pKernelHostVgpuDevice)) 2361 { 2362 if (portMemCmp(pKernelHostVgpuDevice->vgpuUuid, 2363 vgpuUuid, VM_UUID_SIZE) == 0) 2364 { 2365 *ppKernelHostVgpuDevice = pKernelHostVgpuDevice; 2366 return NV_OK; 2367 } 2368 } 2369 2370 return NV_ERR_OBJECT_NOT_FOUND; 2371 } 2372 2373 /* 2374 * On 1GB profiles on 48GB board, we do not deduct any reserved fb from vGPU FB length 2375 * as maxInstance is only 32, so guest complete 1GB of fb mem. In such cases with 2376 * heterogeneous vGPUs, for such 1G profiles on 48G board, some combinations with 2377 * other vGPU types do not work. 2378 * Due to this, A40-8Q at placement Id 0 cannot work with A40-1Q at placement Id 8 since 2379 * A40-1Q is occupying larger vGPU FB length and overlaps with A40-8Q's assigned FB. 2380 * Similar scenario happens for A40-8Q at placement Id 24 and A40-1Q at placement Id 32 2381 * So, we disable 1GB profiles in such cases at placement Id 8 and placement Id 32. 2382 */ 2383 static NvBool 2384 _kvgpumgrIsPlacementValid(OBJGPU *pGpu, KERNEL_PHYS_GPU_INFO *pPgpuInfo, NvU32 vgpuTypeIndex, 2385 NvU32 placementId) 2386 { 2387 NvU64 vgpuFbLength; 2388 NvU32 denyListAdaHopper[] = {2, 3, 8, 9, 14, 15, 20, 21, 26, 27, 32, 33, 38, 39, 44, 45}; 2389 NvU32 denyListAmpere[] = {8, 32}; 2390 NvU32 i, length, *invalidPlacements; 2391 2392 if (IS_GSP_CLIENT(pGpu)) 2393 { 2394 invalidPlacements = denyListAdaHopper; 2395 length = sizeof(denyListAdaHopper) / sizeof(NvU32); 2396 } 2397 else 2398 { 2399 invalidPlacements = denyListAmpere; 2400 length = sizeof(denyListAmpere) / sizeof(NvU32); 2401 } 2402 2403 vgpuFbLength = pPgpuInfo->guestVmmuCount[vgpuTypeIndex] * gpuGetVmmuSegmentSize(pGpu); 2404 2405 if (vgpuFbLength == VGPU_LOWER_FB_PROFILE_SIZE_1_GB) 2406 { 2407 for (i = 0; i < length; i++) 2408 { 2409 if (invalidPlacements[i] == placementId) 2410 return NV_FALSE; 2411 } 2412 } 2413 2414 return NV_TRUE; 2415 } 2416 2417 /* 2418 * This function recursively divides the placement region in 1/2, 1/4, 1/8, 1/16 partitions 2419 * and then calculates the placement IDs of each vGPU type. It will try to allocate 2420 * placement ID of 2 vGPU instances for a type in such a way that the placement ID 2421 * of first vGPU instance starts at the beginning of partition and the placement ID 2422 * of second vGPU instance ends at the end of partition. 2423 * 2424 * It finds the vGPU types whose 2 instances can be allocated in a 1/2, 1/4, 1/8, 1/16 2425 * partition and then allocates one at start of partition and other at end of partion. 2426 * 2427 * It does this recursively by taking input start and end as input alongwith the current 2428 * partition which specifies whether this is 1/1, 1/2, 1/4, 1/8, 1/16 partion. 2429 * 2430 * Similarly it also calculates the channel offsets for each supported placementId 2431 * for a vGPU type. The algorithm for calculating placementId and channel offset 2432 * is the same just that for channel offset the range is from 0 to 2048. 2433 * 2434 * For vGPU-GSP, we also need to define offsets in FB for GSP plugin heap. 2435 * For larger vGPU profiles with GSP plugin heap >=1 vMMU segment, the gsp heap is 2436 * placed at the end of vGPU FB. 2437 * For smaller profiles with gsp heap < 1 vMMU segment, heap is placed at end of 2438 * each 1/4th alignment (for 128MB vMMU segment size) OR 1/8th alighment (for 64MB 2439 * vMMU segment size). For such profiles the vMMU segment at the end of 1/4 or 1/8 2440 * partition is divided as per profile's heap size. 2441 * 2442 */ 2443 static void 2444 _kvgpumgrSetHeterogeneousResources(OBJGPU *pGpu, KERNEL_PHYS_GPU_INFO *pPgpuInfo, NvU32 placementIdMin, 2445 NvU32 placementIdMax, NvU32 chidMin, NvU32 chidMax, 2446 NvU32 vmmuSegMin, NvU32 vmmuSegMax, NvU64 gspHeapOffsetMin, 2447 NvU64 gspHeapOffsetMax, NvU32 partitionCount, 2448 NvBool isLeftPartition) 2449 { 2450 VGPU_TYPE *pVgpuTypeInfo; 2451 NvU32 heterogeneousMaxInstance, i; 2452 NvBool isCarveOutGspHeap = NV_FALSE; 2453 NvU64 newVmmuSegMin, newVmmuSegMax, newGspHeapOffsetMin, newGspHeapOffsetMax, vmmuSegSize; 2454 NvBool isDefineLeftPlacement, isDefineRightPlacement; 2455 2456 /* 2457 * As max vGPU per GPU is 32, the minimum partition for 2 vGPUs will be 16. 2458 * So, if this is a 1/16 partition, don't recurse further 2459 */ 2460 if (partitionCount > MAX_VGPU_DEVICES_PER_PGPU / 2) 2461 return; 2462 2463 vmmuSegSize = gpuGetVmmuSegmentSize(pGpu); 2464 for (i = 0; i < pPgpuInfo->numVgpuTypes; i++) 2465 { 2466 pVgpuTypeInfo = pPgpuInfo->vgpuTypes[i]; 2467 2468 if (pVgpuTypeInfo->placementSize == 0) 2469 continue; 2470 2471 isDefineLeftPlacement = NV_FALSE; 2472 isDefineRightPlacement = NV_FALSE; 2473 2474 heterogeneousMaxInstance = nvPrevPow2_U32(pVgpuTypeInfo->maxInstance); 2475 2476 /* 2477 * If homogeneous maxInstances of vGPU type are in power-of-2 and can fit in this partition, 2478 * then define both the placements in this recursive call 2479 */ 2480 if (partitionCount * 2 == pVgpuTypeInfo->maxInstance) 2481 { 2482 isDefineLeftPlacement = NV_TRUE; 2483 isDefineRightPlacement = NV_TRUE; 2484 2485 /* 2486 * Check if the next recursive partition will be a smaller partition for which 2487 * we need to carve out GSP heap at the end of smaller partition. 2488 */ 2489 if (IS_GSP_CLIENT(pGpu) && (isCarveOutGspHeap == NV_FALSE) && 2490 (pVgpuTypeInfo->gspHeapSize == vmmuSegSize)) 2491 isCarveOutGspHeap = NV_TRUE; 2492 } 2493 else if (((heterogeneousMaxInstance < pVgpuTypeInfo->maxInstance) && 2494 (heterogeneousMaxInstance == partitionCount)) || 2495 ((partitionCount == 1) && (pVgpuTypeInfo->maxInstance == 1))) 2496 { 2497 /* 2498 * If only one instance of vGPU type can fit in this partition, then define 2499 * placement depending on whether it is a left or right partition 2500 */ 2501 isDefineLeftPlacement = isLeftPartition; 2502 isDefineRightPlacement = !isLeftPartition; 2503 } 2504 2505 2506 if (isDefineLeftPlacement == NV_TRUE) 2507 { 2508 /* 2509 * Fill placement ID / channel / FB offset of first vGPU in this partition 2510 * First vGPU is aligned to the starting of partition 2511 */ 2512 if (_kvgpumgrIsPlacementValid(pGpu, pPgpuInfo, i, placementIdMin)) 2513 { 2514 pVgpuTypeInfo->supportedPlacementIds[pVgpuTypeInfo->placementCount] = placementIdMin; 2515 pVgpuTypeInfo->supportedChidOffsets[pVgpuTypeInfo->placementCount] = chidMin; 2516 2517 if (!IS_GSP_CLIENT(pGpu)) 2518 pPgpuInfo->supportedVmmuOffsets[i][pVgpuTypeInfo->placementCount] = vmmuSegMin; 2519 else 2520 { 2521 /* If profile occupies > 1 vMMU segment for GSP heap, place heap at end of vGPU FB. */ 2522 if (pVgpuTypeInfo->gspHeapSize >= vmmuSegSize) 2523 { 2524 pPgpuInfo->supportedVmmuOffsets[i][pVgpuTypeInfo->placementCount] = vmmuSegMin; 2525 pPgpuInfo->gspHeapOffsets[i][pVgpuTypeInfo->placementCount] = 2526 (vmmuSegMin + pPgpuInfo->guestVmmuCount[i]) * vmmuSegSize; 2527 } 2528 else 2529 { 2530 /* 2531 * If we're in smaller parition, GSP vMMU segment will be input to the function. 2532 * Place the gsp heap of first vGPU at the starting of the GSP vMMU segment. 2533 */ 2534 pPgpuInfo->supportedVmmuOffsets[i][pVgpuTypeInfo->placementCount] = vmmuSegMin; 2535 pPgpuInfo->gspHeapOffsets[i][pVgpuTypeInfo->placementCount] = gspHeapOffsetMin; 2536 } 2537 2538 /* For 32:1 vGPU types, the GSP heap is placed between 2 consecutive guest vMMU segments */ 2539 if (heterogeneousMaxInstance == 32) 2540 { 2541 pPgpuInfo->supportedVmmuOffsets[i][pVgpuTypeInfo->placementCount] = vmmuSegMin; 2542 pPgpuInfo->gspHeapOffsets[i][pVgpuTypeInfo->placementCount] = 2543 (vmmuSegMin + pPgpuInfo->guestVmmuCount[i]) * vmmuSegSize; 2544 } 2545 } 2546 2547 pVgpuTypeInfo->placementCount++; 2548 } 2549 } 2550 2551 if (isDefineRightPlacement == NV_TRUE) 2552 { 2553 /* 2554 * Fill placement ID / channel / FB offset of second vGPU in this partition 2555 * Second vGPU is aligned to the end of partition 2556 */ 2557 if (_kvgpumgrIsPlacementValid(pGpu, pPgpuInfo, i, 2558 placementIdMax - pVgpuTypeInfo->placementSize)) 2559 { 2560 pVgpuTypeInfo->supportedPlacementIds[pVgpuTypeInfo->placementCount] = 2561 placementIdMax - pVgpuTypeInfo->placementSize; 2562 2563 pVgpuTypeInfo->supportedChidOffsets[pVgpuTypeInfo->placementCount] = 2564 chidMax - pVgpuTypeInfo->channelCount; 2565 2566 if (!IS_GSP_CLIENT(pGpu)) 2567 pPgpuInfo->supportedVmmuOffsets[i][pVgpuTypeInfo->placementCount] = 2568 vmmuSegMax - pPgpuInfo->guestVmmuCount[i]; 2569 else 2570 { 2571 /* If profile occupies > 1 vMMU segment for GSP heap, place heap at end of vGPU FB. */ 2572 if (pVgpuTypeInfo->gspHeapSize >= vmmuSegSize) 2573 { 2574 pPgpuInfo->supportedVmmuOffsets[i][pVgpuTypeInfo->placementCount] = 2575 vmmuSegMax - pPgpuInfo->guestVmmuCount[i] - (pVgpuTypeInfo->gspHeapSize / vmmuSegSize); 2576 pPgpuInfo->gspHeapOffsets[i][pVgpuTypeInfo->placementCount] = 2577 (vmmuSegMax * vmmuSegSize) - pVgpuTypeInfo->gspHeapSize; 2578 } 2579 else 2580 { 2581 /* 2582 * If we're in smaller parition, GSP vMMU segment will be input to the function. 2583 * Place the gsp heap of first vGPU at the starting of the GSP vMMU segment. 2584 */ 2585 pPgpuInfo->supportedVmmuOffsets[i][pVgpuTypeInfo->placementCount] = 2586 vmmuSegMax - pPgpuInfo->guestVmmuCount[i]; 2587 pPgpuInfo->gspHeapOffsets[i][pVgpuTypeInfo->placementCount] = 2588 gspHeapOffsetMax - pVgpuTypeInfo->gspHeapSize; 2589 } 2590 2591 /* For 32:1 vGPU types, the GSP heap is placed between 2 consecutive guest vMMU segments */ 2592 if (heterogeneousMaxInstance == 32) 2593 { 2594 pPgpuInfo->supportedVmmuOffsets[i][pVgpuTypeInfo->placementCount] = 2595 vmmuSegMax - pPgpuInfo->guestVmmuCount[i]; 2596 pPgpuInfo->gspHeapOffsets[i][pVgpuTypeInfo->placementCount] = 2597 ((vmmuSegMax - pPgpuInfo->guestVmmuCount[i]) * vmmuSegSize) - pVgpuTypeInfo->gspHeapSize; 2598 } 2599 } 2600 2601 pVgpuTypeInfo->placementCount++; 2602 } 2603 } 2604 } 2605 2606 /* 2607 * If the next recursive partition is for smaller partition which has GSP heap at 2608 * of end of partition, then update vmmuSegMax to reserve one segment at the 2609 * end of smaller partition. Also, init gsp min/max value for the reserved vMMU segment 2610 * at the end. 2611 */ 2612 newVmmuSegMin = vmmuSegMin; 2613 if ((isCarveOutGspHeap == NV_TRUE)) 2614 { 2615 NV_ASSERT((gspHeapOffsetMin == 0)); 2616 2617 newVmmuSegMax = ((vmmuSegMin + vmmuSegMax) / 2) - 1; 2618 newGspHeapOffsetMin = newVmmuSegMax * vmmuSegSize; 2619 newGspHeapOffsetMax = newGspHeapOffsetMin + vmmuSegSize; 2620 } 2621 else 2622 { 2623 newVmmuSegMax = (vmmuSegMin + vmmuSegMax) / 2; 2624 newGspHeapOffsetMin = gspHeapOffsetMin; 2625 newGspHeapOffsetMax = (gspHeapOffsetMin + gspHeapOffsetMax) / 2; 2626 } 2627 2628 /* Recursively call to get placment ID in first half of this partition */ 2629 _kvgpumgrSetHeterogeneousResources(pGpu, pPgpuInfo, placementIdMin, 2630 (placementIdMin + placementIdMax) / 2, 2631 chidMin, (chidMin + chidMax) / 2, newVmmuSegMin, 2632 newVmmuSegMax, newGspHeapOffsetMin, newGspHeapOffsetMax, partitionCount * 2, 2633 NV_TRUE); 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 second 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