1 /* 2 * SPDX-FileCopyrightText: Copyright (c) 2021-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 #define NVOC_KERNEL_MIG_MANAGER_H_PRIVATE_ACCESS_ALLOWED 25 26 #include "kernel/gpu/mem_mgr/mem_mgr.h" 27 #include "kernel/gpu/mem_mgr/heap.h" 28 #include "kernel/gpu/mig_mgr/kernel_mig_manager.h" 29 #include "kernel/gpu/fifo/kernel_fifo.h" 30 #include "gpu/bus/kern_bus.h" 31 32 #include "published/ampere/ga100/dev_bus.h" 33 #include "published/ampere/ga100/dev_bus_addendum.h" 34 35 /*! 36 * @brief Checks Devinit owned scratch bit to see if MIG is enabled or not 37 * 38 * @return NV_TRUE if scratch bit is set else NV_FALSE 39 */ 40 NvBool 41 kmigmgrIsDevinitMIGBitSet_GA100 42 ( 43 OBJGPU *pGpu, 44 KernelMIGManager *pKernelMIGManager 45 ) 46 { 47 NvU32 regVal; 48 49 regVal = GPU_REG_RD32(pGpu, NV_PBUS_SW_SCRATCH(1)); 50 51 return FLD_TEST_DRF(_PBUS, _SW_SCRATCH1_SMC,_MODE, _ON, regVal); 52 } 53 54 /*! 55 * @brief Peforms checks to determine whether instancing can be enabled on 56 * this GPU, such as determining whether any partitionable engines are 57 * currently active. 58 */ 59 NV_STATUS 60 kmigmgrCreateGPUInstanceCheck_GA100 61 ( 62 OBJGPU *pGpu, 63 KernelMIGManager *pKernelMIGManager, 64 NvBool bMemoryPartitioningNeeded 65 ) 66 { 67 Heap *pHeap; 68 KernelFifo *pKernelFifo = GPU_GET_KERNEL_FIFO(pGpu); 69 RM_ENGINE_TYPE engines[RM_ENGINE_TYPE_LAST]; 70 NvU32 engineCount; 71 NvU32 i; 72 NvU64 largestFreeSize; 73 NvU64 base; 74 NvU64 unused; 75 NV_RANGE freeBlock; 76 MemoryManager *pMemoryManager = GPU_GET_MEMORY_MANAGER(pGpu); 77 NV_RANGE partitionableMemoryRange = memmgrGetMIGPartitionableMemoryRange(pGpu, pMemoryManager); 78 79 // Ensure the engine DB is up-to-date 80 NV_ASSERT_OK_OR_RETURN(gpuUpdateEngineTable(pGpu)); 81 82 // Store all engine tags of partitionable engines in the system 83 engineCount = 0; 84 for (i = 0; i < pGpu->engineDB.size; ++i) 85 { 86 if (kmigmgrIsEnginePartitionable(pGpu, pKernelMIGManager, pGpu->engineDB.pType[i])) 87 { 88 // 89 // If memory partitioning isnt needed, scrubber channel will be active, and 90 // partitioning isn't really a destructive operation anyway, so 91 // skip checking for copy engines 92 // 93 if (RM_ENGINE_TYPE_IS_COPY(pGpu->engineDB.pType[i]) && 94 !bMemoryPartitioningNeeded) 95 { 96 continue; 97 } 98 99 if (RM_ENGINE_TYPE_IS_GR(pGpu->engineDB.pType[i]) && 100 (RM_ENGINE_TYPE_GR_IDX(pGpu->engineDB.pType[i]) > 0)) 101 { 102 // 103 // This check is used during GPU instance creation, prior to which 104 // it is impossible to use GR1-7, so as an optimization, skip 105 // checking for those. 106 // 107 continue; 108 } 109 110 engines[engineCount++] = pGpu->engineDB.pType[i]; 111 } 112 } 113 114 // Make sure there are no channels alive on any of these engines 115 if (kfifoEngineListHasChannel(pGpu, pKernelFifo, engines, engineCount)) 116 return NV_ERR_STATE_IN_USE; 117 118 // 119 // Check for any alive P2P references to this GPU. P2P objects must 120 // be re-created after disabling MIG. If it is allowed for MIG to 121 // continue enablement without all P2P objects torn down, there is 122 // the possibility that P2P mappings and state will never be updated. 123 // 124 if (bMemoryPartitioningNeeded || !kmigmgrIsMIGNvlinkP2PSupportOverridden(pGpu, pKernelMIGManager)) 125 { 126 NV_CHECK_OR_RETURN(LEVEL_ERROR, 127 !kbusIsGpuP2pAlive(pGpu, GPU_GET_KERNEL_BUS(pGpu)), 128 NV_ERR_STATE_IN_USE); 129 } 130 131 pHeap = GPU_GET_HEAP(pGpu); 132 if (!memmgrIsPmaInitialized(pMemoryManager)) 133 { 134 NV_ASSERT_OK_OR_RETURN( 135 heapInfo(pHeap, &unused, &unused, &unused, &base, &largestFreeSize)); 136 } 137 else 138 { 139 pmaGetLargestFree(&pHeap->pmaObject, &largestFreeSize, &base, &unused); 140 } 141 142 // Make sure that no memory has been claimed from our partitionable range 143 freeBlock = rangeMake(base, base + largestFreeSize - 1); 144 if (!rangeContains(freeBlock, partitionableMemoryRange)) 145 return NV_ERR_STATE_IN_USE; 146 147 return NV_OK; 148 } 149 150 /*! 151 * @brief Function to determine whether gpu instance flags are valid 152 * for this GPU 153 * 154 * @param[IN] pGpu 155 * @param[IN] pKernelMIGManager 156 * @param[IN] gpuInstanceFlag NV2080_CTRL_GPU_PARTITION_FLAG_* 157 * 158 * @return Returns true if flags are valid 159 */ 160 NvBool 161 kmigmgrIsGPUInstanceFlagValid_GA100 162 ( 163 OBJGPU *pGpu, 164 KernelMIGManager *pGrMgr, 165 NvU32 gpuInstanceFlag 166 ) 167 { 168 NvU32 memSizeFlag = DRF_VAL(2080_CTRL_GPU, _PARTITION_FLAG, 169 _MEMORY_SIZE, gpuInstanceFlag); 170 NvU32 computeSizeFlag = DRF_VAL(2080_CTRL_GPU, _PARTITION_FLAG, 171 _COMPUTE_SIZE, gpuInstanceFlag); 172 173 switch (memSizeFlag) 174 { 175 case NV2080_CTRL_GPU_PARTITION_FLAG_MEMORY_SIZE_FULL: 176 case NV2080_CTRL_GPU_PARTITION_FLAG_MEMORY_SIZE_HALF: 177 case NV2080_CTRL_GPU_PARTITION_FLAG_MEMORY_SIZE_QUARTER: 178 case NV2080_CTRL_GPU_PARTITION_FLAG_MEMORY_SIZE_EIGHTH: 179 break; 180 default: 181 NV_PRINTF(LEVEL_ERROR, "Unrecognized GPU mem partitioning flag 0x%x\n", 182 memSizeFlag); 183 return NV_FALSE; 184 } 185 186 switch (computeSizeFlag) 187 { 188 case NV2080_CTRL_GPU_PARTITION_FLAG_COMPUTE_SIZE_FULL: 189 case NV2080_CTRL_GPU_PARTITION_FLAG_COMPUTE_SIZE_HALF: 190 case NV2080_CTRL_GPU_PARTITION_FLAG_COMPUTE_SIZE_MINI_HALF: 191 case NV2080_CTRL_GPU_PARTITION_FLAG_COMPUTE_SIZE_QUARTER: 192 case NV2080_CTRL_GPU_PARTITION_FLAG_COMPUTE_SIZE_MINI_QUARTER: 193 case NV2080_CTRL_GPU_PARTITION_FLAG_COMPUTE_SIZE_EIGHTH: 194 break; 195 default: 196 NV_PRINTF(LEVEL_ERROR, "Unrecognized GPU compute partitioning flag 0x%x\n", 197 computeSizeFlag); 198 return NV_FALSE; 199 } 200 201 return NV_TRUE; 202 } 203 204 /*! 205 * @brief Function to determine whether gpu instance flag combinations are valid 206 * for this GPU 207 */ 208 NvBool 209 kmigmgrIsGPUInstanceCombinationValid_GA100 210 ( 211 OBJGPU *pGpu, 212 KernelMIGManager *pKernelMIGManager, 213 NvU32 gpuInstanceFlag 214 ) 215 { 216 NvU32 memSizeFlag = DRF_VAL(2080_CTRL_GPU, _PARTITION_FLAG, _MEMORY_SIZE, gpuInstanceFlag); 217 NvU32 computeSizeFlag = DRF_VAL(2080_CTRL_GPU, _PARTITION_FLAG, _COMPUTE_SIZE, gpuInstanceFlag); 218 219 if (!kmigmgrIsGPUInstanceFlagValid_HAL(pGpu, pKernelMIGManager, gpuInstanceFlag)) 220 { 221 return NV_FALSE; 222 } 223 224 // JPG_OFA profile is only available on the smallest partition 225 if (FLD_TEST_REF(NV2080_CTRL_GPU_PARTITION_FLAG_REQ_DEC_JPG_OFA, _ENABLE, gpuInstanceFlag)) 226 { 227 if (kmigmgrIsA100ReducedConfig(pGpu, pKernelMIGManager)) 228 { 229 if ((computeSizeFlag != NV2080_CTRL_GPU_PARTITION_FLAG_COMPUTE_SIZE_HALF) && 230 (computeSizeFlag != NV2080_CTRL_GPU_PARTITION_FLAG_COMPUTE_SIZE_QUARTER)) 231 { 232 return NV_FALSE; 233 } 234 } 235 else if (computeSizeFlag != NV2080_CTRL_GPU_PARTITION_FLAG_COMPUTE_SIZE_EIGHTH) 236 { 237 return NV_FALSE; 238 } 239 } 240 241 if (kmigmgrIsA100ReducedConfig(pGpu, pKernelMIGManager) && 242 ((computeSizeFlag == NV2080_CTRL_GPU_PARTITION_FLAG_COMPUTE_SIZE_MINI_HALF) || 243 (computeSizeFlag == NV2080_CTRL_GPU_PARTITION_FLAG_COMPUTE_SIZE_MINI_QUARTER))) 244 { 245 return NV_FALSE; 246 } 247 248 switch (computeSizeFlag) 249 { 250 case NV2080_CTRL_GPU_PARTITION_FLAG_COMPUTE_SIZE_FULL: 251 NV_CHECK_OR_RETURN(LEVEL_SILENT, memSizeFlag == NV2080_CTRL_GPU_PARTITION_FLAG_MEMORY_SIZE_FULL, 252 NV_FALSE); 253 break; 254 case NV2080_CTRL_GPU_PARTITION_FLAG_COMPUTE_SIZE_HALF: 255 NV_CHECK_OR_RETURN(LEVEL_SILENT, memSizeFlag == NV2080_CTRL_GPU_PARTITION_FLAG_MEMORY_SIZE_HALF, 256 NV_FALSE); 257 break; 258 case NV2080_CTRL_GPU_PARTITION_FLAG_COMPUTE_SIZE_MINI_HALF: 259 NV_CHECK_OR_RETURN(LEVEL_SILENT, memSizeFlag == NV2080_CTRL_GPU_PARTITION_FLAG_MEMORY_SIZE_HALF, 260 NV_FALSE); 261 break; 262 case NV2080_CTRL_GPU_PARTITION_FLAG_COMPUTE_SIZE_QUARTER: 263 NV_CHECK_OR_RETURN(LEVEL_SILENT, memSizeFlag == NV2080_CTRL_GPU_PARTITION_FLAG_MEMORY_SIZE_QUARTER, 264 NV_FALSE); 265 break; 266 case NV2080_CTRL_GPU_PARTITION_FLAG_COMPUTE_SIZE_MINI_QUARTER: 267 NV_CHECK_OR_RETURN(LEVEL_SILENT, memSizeFlag == NV2080_CTRL_GPU_PARTITION_FLAG_MEMORY_SIZE_QUARTER, 268 NV_FALSE); 269 break; 270 case NV2080_CTRL_GPU_PARTITION_FLAG_COMPUTE_SIZE_EIGHTH: 271 NV_CHECK_OR_RETURN(LEVEL_SILENT, memSizeFlag == NV2080_CTRL_GPU_PARTITION_FLAG_MEMORY_SIZE_EIGHTH, 272 NV_FALSE); 273 break; 274 default: 275 NV_ASSERT(0); 276 return NV_FALSE; 277 } 278 279 return NV_TRUE; 280 } 281 282 /*! 283 * @brief Returns the range of swizzids which can be assigned to a GPU 284 * instance of the given size. 285 * 286 * @param[IN] pGpu 287 * @param[IN] pKernelMIGManager 288 * @param[IN] memSizeFlag NV2080_CTRL_GPU_PARTITION_FLAG_MEMORY_SIZE_* 289 */ 290 NV_RANGE 291 kmigmgrMemSizeFlagToSwizzIdRange_GA100 292 ( 293 OBJGPU *pGpu, 294 KernelMIGManager *pKernelMIGManager, 295 NvU32 memSizeFlag 296 ) 297 { 298 NV_RANGE ret; 299 300 switch (DRF_VAL(2080_CTRL_GPU, _PARTITION_FLAG, _MEMORY_SIZE, memSizeFlag)) 301 { 302 case NV2080_CTRL_GPU_PARTITION_FLAG_MEMORY_SIZE_FULL: 303 { 304 ret = rangeMake(0, 0); 305 break; 306 } 307 308 case NV2080_CTRL_GPU_PARTITION_FLAG_MEMORY_SIZE_HALF: 309 { 310 ret = rangeMake(1, 2); 311 break; 312 } 313 314 case NV2080_CTRL_GPU_PARTITION_FLAG_MEMORY_SIZE_QUARTER: 315 { 316 ret = rangeMake(3, 6); 317 break; 318 } 319 320 case NV2080_CTRL_GPU_PARTITION_FLAG_MEMORY_SIZE_EIGHTH: 321 { 322 ret = rangeMake(7, 14); 323 break; 324 } 325 326 default: 327 { 328 NV_PRINTF(LEVEL_ERROR, "Unsupported mem size flag 0x%x\n", 329 memSizeFlag); 330 DBG_BREAKPOINT(); 331 ret = NV_RANGE_EMPTY; 332 break; 333 } 334 } 335 return ret; 336 } 337 /*! 338 * @brief Checks if user requested a configuration that should require memory partitioning 339 * 340 * @param[IN] pGpu 341 * @param[IN] pKernelMIGManager 342 * @param[IN] partitionFlags Client request flags 343 */ 344 NvBool 345 kmigmgrIsMemoryPartitioningRequested_GA100 346 ( 347 OBJGPU *pGpu, 348 KernelMIGManager *pKernelMIGManager, 349 NvU32 partitionFlags 350 ) 351 { 352 NvU32 memSizeFlag = DRF_VAL(2080_CTRL_GPU, _PARTITION_FLAG, _MEMORY_SIZE, partitionFlags); 353 return (memSizeFlag != NV2080_CTRL_GPU_PARTITION_FLAG_MEMORY_SIZE_FULL); 354 } 355 356 /*! 357 * @brief Checks if memory partitioning will be needed for a given swizzId 358 */ 359 NvBool 360 kmigmgrIsMemoryPartitioningNeeded_GA100 361 ( 362 OBJGPU *pGpu, 363 KernelMIGManager *pKernelMIGManager, 364 NvU32 swizzId 365 ) 366 { 367 // Memory partitioning is needed for non-zero swizzIds 368 return (swizzId != 0); 369 } 370