1 /* 2 * SPDX-FileCopyrightText: Copyright (c) 1993-2022 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 "core/core.h" 25 #include "gpu/gpu.h" 26 #include "gpu/mem_mgr/mem_mgr.h" 27 #include "gpu/mem_sys/kern_mem_sys.h" 28 #include "gpu/mem_mgr/heap.h" 29 #include "gpu/bus/kern_bus.h" 30 #include "kernel/gpu/mig_mgr/kernel_mig_manager.h" 31 #include "gpu/mem_mgr/mem_desc.h" 32 #include "gpu/mem_mgr/virt_mem_allocator.h" 33 #include "gpu/gpu_resource_desc.h" 34 #include "gpu/subdevice/subdevice.h" 35 #include "platform/chipset/chipset.h" 36 #include "ctrl/ctrl0080/ctrl0080fb.h" 37 #include "ctrl/ctrl2080/ctrl2080fb.h" 38 #include "core/locks.h" 39 #include "vgpu/rpc.h" 40 #include "rmapi/client.h" 41 42 43 static NV_STATUS 44 _fbGetFbInfos(OBJGPU *pGpu, NvHandle hClient, NvHandle hObject, NV2080_CTRL_FB_INFO *pFbInfos, NvU32 fbInfoListSize) 45 { 46 KernelMemorySystem *pKernelMemorySystem = GPU_GET_KERNEL_MEMORY_SYSTEM(pGpu); 47 MemoryManager *pMemoryManager = GPU_GET_MEMORY_MANAGER(pGpu); 48 Heap *pHeap = GPU_GET_HEAP(pGpu); 49 Heap *pMemoryPartitionHeap = NULL; 50 KernelMIGManager *pKernelMIGManager = GPU_GET_KERNEL_MIG_MANAGER(pGpu); 51 NV_STATUS status = NV_OK; 52 NvU32 data = 0; 53 NvU32 i = 0; 54 NvBool bIsPmaEnabled = memmgrIsPmaInitialized(pMemoryManager); 55 NvBool bIsMIGInUse = IS_MIG_IN_USE(pGpu); 56 NvU64 bytesTotal; 57 NvU64 bytesFree; 58 NvU64 heapBase; 59 NvU64 largestOffset; 60 NvU64 largestFree; 61 NvU64 val; 62 NvU64 routeToPhysicalIdxMask = 0; 63 NvBool bIsClientMIGMonitor = NV_FALSE; 64 NvBool bIsClientMIGProfiler = NV_FALSE; 65 66 ct_assert(NV2080_CTRL_FB_INFO_INDEX_MAX < NV_NBITS_IN_TYPE(routeToPhysicalIdxMask)); 67 68 if (!RMCFG_FEATURE_PMA) 69 return NV_ERR_NOT_SUPPORTED; 70 71 if (bIsMIGInUse) 72 { 73 bIsClientMIGMonitor = !RMCFG_FEATURE_PLATFORM_GSP && rmclientIsCapableByHandle(hClient, NV_RM_CAP_SYS_SMC_MONITOR); 74 bIsClientMIGProfiler = kmigmgrIsClientUsingDeviceProfiling(pGpu, pKernelMIGManager, hClient); 75 } 76 77 // 78 // Most MIG queries require GPU instance info that is only kept in the Physical RM. Flag 79 // the indices that will need to be fulfilled by the GSP when in offload mode, and 80 // also load the per-GPU instance heap for others. 81 // 82 for (i = 0; i < fbInfoListSize; i++) 83 { 84 switch (pFbInfos[i].index) 85 { 86 // The cases which aren't affected by MIG 87 case NV2080_CTRL_FB_INFO_INDEX_TILE_REGION_COUNT: 88 case NV2080_CTRL_FB_INFO_INDEX_TILE_REGION_FREE_COUNT: 89 case NV2080_CTRL_FB_INFO_INDEX_BANK_SWIZZLE_ALIGNMENT: 90 case NV2080_CTRL_FB_INFO_INDEX_BANK_COUNT: 91 case NV2080_CTRL_FB_INFO_INDEX_OVERLAY_OFFSET_ADJUSTMENT: 92 case NV2080_CTRL_FB_INFO_INDEX_FB_TAX_SIZE_KB: 93 case NV2080_CTRL_FB_INFO_INDEX_RAM_LOCATION: 94 case NV2080_CTRL_FB_INFO_INDEX_FB_IS_BROKEN: 95 case NV2080_CTRL_FB_INFO_INDEX_L2CACHE_ONLY_MODE: 96 case NV2080_CTRL_FB_INFO_INDEX_SMOOTHDISP_RSVD_BAR1_SIZE: 97 case NV2080_CTRL_FB_INFO_INDEX_HEAP_OFFLINE_SIZE: 98 case NV2080_CTRL_FB_INFO_INDEX_SUSPEND_RESUME_RSVD_SIZE: 99 case NV2080_CTRL_FB_INFO_INDEX_ALLOW_PAGE_RETIREMENT: 100 case NV2080_CTRL_FB_INFO_POISON_FUSE_ENABLED: 101 case NV2080_CTRL_FB_INFO_FBPA_ECC_ENABLED: 102 case NV2080_CTRL_FB_INFO_DYNAMIC_PAGE_OFFLINING_ENABLED: 103 case NV2080_CTRL_FB_INFO_INDEX_FORCED_BAR1_64KB_MAPPING_ENABLED: 104 case NV2080_CTRL_FB_INFO_INDEX_P2P_MAILBOX_SIZE: 105 case NV2080_CTRL_FB_INFO_INDEX_P2P_MAILBOX_ALIGNMENT: 106 case NV2080_CTRL_FB_INFO_INDEX_P2P_MAILBOX_BAR1_MAX_OFFSET_64KB: 107 { 108 continue; 109 } 110 case NV2080_CTRL_FB_INFO_INDEX_BUS_WIDTH: 111 case NV2080_CTRL_FB_INFO_INDEX_PARTITION_COUNT: 112 case NV2080_CTRL_FB_INFO_INDEX_PARTITION_MASK: 113 case NV2080_CTRL_FB_INFO_INDEX_FBP_MASK: 114 case NV2080_CTRL_FB_INFO_INDEX_FBP_COUNT: 115 case NV2080_CTRL_FB_INFO_INDEX_L2CACHE_SIZE: 116 case NV2080_CTRL_FB_INFO_INDEX_LTC_COUNT: 117 case NV2080_CTRL_FB_INFO_INDEX_LTS_COUNT: 118 case NV2080_CTRL_FB_INFO_INDEX_LTC_MASK: 119 case NV2080_CTRL_FB_INFO_INDEX_MEMORYINFO_VENDOR_ID: 120 case NV2080_CTRL_FB_INFO_INDEX_TRAINIG_2T: 121 case NV2080_CTRL_FB_INFO_INDEX_PSEUDO_CHANNEL_MODE: 122 case NV2080_CTRL_FB_INFO_INDEX_COMPRESSION_SIZE: 123 case NV2080_CTRL_FB_INFO_INDEX_DRAM_PAGE_STRIDE: 124 case NV2080_CTRL_FB_INFO_INDEX_RAM_CFG: 125 case NV2080_CTRL_FB_INFO_INDEX_RAM_TYPE: 126 case NV2080_CTRL_FB_INFO_INDEX_ECC_STATUS_SIZE: 127 { 128 // This info is only known by the Physical RM. Redirect it there. 129 if (IS_GSP_CLIENT(pGpu)) 130 { 131 routeToPhysicalIdxMask |= BIT64(i); 132 } 133 134 break; 135 } 136 case NV2080_CTRL_FB_INFO_INDEX_TOTAL_RAM_SIZE: 137 case NV2080_CTRL_FB_INFO_INDEX_RAM_SIZE: 138 { 139 // 140 // If MIG is enabled and device profiling/monitoring 141 // is not in use we check for GPU instance subscription 142 // and provide GPU instance local info. Unsubscribed + unprivileged 143 // clients may still query global info for the above list of 144 // indices. 145 // 146 if (bIsMIGInUse && 147 !bIsClientMIGProfiler && !bIsClientMIGMonitor) 148 { 149 MIG_INSTANCE_REF ref; 150 status = kmigmgrGetInstanceRefFromClient(pGpu, pKernelMIGManager, 151 hClient, &ref); 152 153 if ((status != NV_OK) && !kmigmgrIsMIGReferenceValid(&ref)) 154 { 155 status = NV_OK; 156 break; 157 } 158 } 159 160 // Fall through to the default case to get the memory partition heap 161 } 162 default: 163 { 164 // 165 // If MIG is enabled and device profiling/monitoring 166 // is not in use we check for GPU instance subscription 167 // and provide GPU instance local info 168 // 169 if (bIsMIGInUse && 170 !bIsClientMIGProfiler && !bIsClientMIGMonitor) 171 { 172 NV_CHECK_OR_RETURN(LEVEL_INFO, (kmigmgrGetMemoryPartitionHeapFromClient(pGpu, 173 pKernelMIGManager, hClient, &pMemoryPartitionHeap) == NV_OK), 174 NV_ERR_INSUFFICIENT_PERMISSIONS); 175 176 // 177 // If client is associated with a GPU instance then point pHeap 178 // to client's memory partition heap 179 // 180 if (pMemoryPartitionHeap != NULL) 181 pHeap = pMemoryPartitionHeap; 182 } 183 break; 184 } 185 } 186 } 187 188 // If we have any infos that need to be populated by Physical RM, query now 189 if (routeToPhysicalIdxMask != 0) 190 { 191 RM_API *pRmApi = GPU_GET_PHYSICAL_RMAPI(pGpu); 192 NV2080_CTRL_FB_GET_INFO_V2_PARAMS *pParams = 193 portMemAllocNonPaged(sizeof(NV2080_CTRL_FB_GET_INFO_V2_PARAMS)); 194 NvU32 physIdx = 0; 195 196 portMemSet(pParams, 0, sizeof(*pParams)); 197 FOR_EACH_INDEX_IN_MASK(64, i, routeToPhysicalIdxMask) 198 { 199 pParams->fbInfoList[physIdx++].index = pFbInfos[i].index; 200 } 201 FOR_EACH_INDEX_IN_MASK_END; 202 203 pParams->fbInfoListSize = physIdx; 204 205 NV_CHECK_OK_OR_ELSE(status, LEVEL_ERROR, 206 pRmApi->Control(pRmApi, hClient, hObject, 207 NV2080_CTRL_CMD_FB_GET_INFO_V2, 208 pParams, sizeof(*pParams)), 209 portMemFree(pParams); 210 return status; 211 ); 212 213 physIdx = 0; 214 FOR_EACH_INDEX_IN_MASK(64, i, routeToPhysicalIdxMask) 215 { 216 NV_ASSERT(pFbInfos[i].index == pParams->fbInfoList[physIdx].index); 217 pFbInfos[i].data = pParams->fbInfoList[physIdx++].data; 218 } 219 FOR_EACH_INDEX_IN_MASK_END; 220 221 portMemFree(pParams); 222 } 223 224 for (i = 0; i < fbInfoListSize; i++) 225 { 226 // Skip info already populated by Physical RM 227 if ((routeToPhysicalIdxMask & BIT64(i)) != 0) 228 continue; 229 230 switch (pFbInfos[i].index) 231 { 232 case NV2080_CTRL_FB_INFO_INDEX_TILE_REGION_COUNT: 233 { 234 data = 0; 235 break; 236 } 237 case NV2080_CTRL_FB_INFO_INDEX_TILE_REGION_FREE_COUNT: 238 { 239 // Obsolete 240 data = 0; 241 break; 242 } 243 case NV2080_CTRL_FB_INFO_INDEX_BAR1_SIZE: 244 { 245 GETBAR1INFO bar1Info = {0}; 246 status = memmgrGetBAR1InfoForClient_HAL(pGpu, pMemoryManager, hClient, &bar1Info); 247 if (status != NV_OK) 248 data = 0; 249 else 250 data = bar1Info.bar1Size; 251 252 break; 253 } 254 case NV2080_CTRL_FB_INFO_INDEX_BAR1_AVAIL_SIZE: 255 { 256 GETBAR1INFO bar1Info = {0}; 257 status = memmgrGetBAR1InfoForClient_HAL(pGpu, pMemoryManager, hClient, &bar1Info); 258 if (status != NV_OK) 259 data = 0; 260 else 261 data = bar1Info.bar1AvailSize; 262 263 break; 264 } 265 case NV2080_CTRL_FB_INFO_INDEX_BAR1_MAX_CONTIGUOUS_AVAIL_SIZE: 266 { 267 GETBAR1INFO bar1Info = {0}; 268 status = memmgrGetBAR1InfoForClient_HAL(pGpu, pMemoryManager, hClient, &bar1Info); 269 if (status != NV_OK) 270 data = 0; 271 else 272 data = bar1Info.bar1MaxContigAvailSize; 273 274 break; 275 } 276 case NV2080_CTRL_FB_INFO_INDEX_BANK_SWIZZLE_ALIGNMENT: 277 { 278 GETBAR1INFO bar1Info = {0}; 279 status = memmgrGetBAR1InfoForClient_HAL(pGpu, pMemoryManager, hClient, &bar1Info); 280 if (status != NV_OK) 281 data = 0; 282 else 283 data = bar1Info.bankSwizzleAlignment; 284 285 break; 286 } 287 case NV2080_CTRL_FB_INFO_INDEX_TOTAL_RAM_SIZE: 288 { 289 if (pMemoryPartitionHeap != NULL) 290 { 291 NvU32 heapSizeKb; 292 if (bIsPmaEnabled) 293 { 294 pmaGetTotalMemory(&pHeap->pmaObject, &bytesTotal); 295 NV_ASSERT(NvU64_HI32(bytesTotal >> 10) == 0); 296 heapSizeKb = NvU64_LO32(bytesTotal >> 10); 297 } 298 else 299 { 300 NvU64 size; 301 302 heapGetSize(pHeap, &size); 303 NV_ASSERT(NvU64_HI32(size >> 10) == 0); 304 heapSizeKb = NvU64_LO32(size >> 10); 305 } 306 data = heapSizeKb; 307 break; 308 } 309 else 310 { 311 const MEMORY_SYSTEM_STATIC_CONFIG *pMemsysConfig = 312 kmemsysGetStaticConfig(pGpu, pKernelMemorySystem); 313 NV_ASSERT(0 == NvU64_HI32(pMemoryManager->Ram.fbTotalMemSizeMb << 10)); 314 data = NvU64_LO32(NV_MIN((pMemoryManager->Ram.fbTotalMemSizeMb << 10), 315 (pMemoryManager->Ram.fbOverrideSizeMb << 10)) 316 - pMemsysConfig->fbOverrideStartKb); 317 break; 318 } 319 } 320 case NV2080_CTRL_FB_INFO_INDEX_RAM_SIZE: 321 { 322 const MEMORY_SYSTEM_STATIC_CONFIG *pMemsysConfig = 323 kmemsysGetStaticConfig(pGpu, pKernelMemorySystem); 324 if (pMemoryPartitionHeap != NULL) 325 { 326 NvU32 heapSizeKb; 327 if (bIsPmaEnabled) 328 { 329 pmaGetTotalMemory(&pHeap->pmaObject, &bytesTotal); 330 NV_ASSERT(NvU64_HI32(bytesTotal >> 10) == 0); 331 heapSizeKb = NvU64_LO32(bytesTotal >> 10); 332 } 333 else 334 { 335 NvU64 size; 336 337 heapGetSize(pHeap, &size); 338 NV_ASSERT(NvU64_HI32(size >> 10) == 0); 339 heapSizeKb = NvU64_LO32(size >> 10); 340 } 341 data = heapSizeKb; 342 break; 343 } 344 NV_ASSERT(0 == NvU64_HI32(pMemoryManager->Ram.fbTotalMemSizeMb << 10)); 345 data = NvU64_LO32(NV_MIN((pMemoryManager->Ram.fbTotalMemSizeMb << 10), 346 (pMemoryManager->Ram.fbOverrideSizeMb << 10)) 347 - pMemsysConfig->fbOverrideStartKb); 348 break; 349 } 350 case NV2080_CTRL_FB_INFO_INDEX_USABLE_RAM_SIZE: 351 { 352 const MEMORY_SYSTEM_STATIC_CONFIG *pMemsysConfig = 353 kmemsysGetStaticConfig(pGpu, pKernelMemorySystem); 354 if (pMemoryPartitionHeap != NULL) 355 { 356 NvU32 heapSizeKb; 357 if (bIsPmaEnabled) 358 { 359 pmaGetTotalMemory(&pHeap->pmaObject, &bytesTotal); 360 NV_ASSERT(NvU64_HI32(bytesTotal >> 10) == 0); 361 heapSizeKb = NvU64_LO32(bytesTotal >> 10); 362 } 363 else 364 { 365 NvU64 size; 366 367 heapGetSize(pHeap, &size); 368 NV_ASSERT(NvU64_HI32(size >> 10) == 0); 369 heapSizeKb = NvU64_LO32(size >> 10); 370 } 371 data = heapSizeKb; 372 break; 373 } 374 NV_ASSERT(0 == NvU64_HI32(pMemoryManager->Ram.fbUsableMemSize >> 10)); 375 data = NvU64_LO32(NV_MIN((pMemoryManager->Ram.fbUsableMemSize >> 10 ), 376 (pMemoryManager->Ram.fbOverrideSizeMb << 10)) 377 - pMemsysConfig->fbOverrideStartKb); 378 break; 379 } 380 case NV2080_CTRL_FB_INFO_INDEX_HEAP_SIZE: 381 { 382 const MEMORY_SYSTEM_STATIC_CONFIG *pMemsysConfig = 383 kmemsysGetStaticConfig(pGpu, pKernelMemorySystem); 384 if (bIsPmaEnabled) 385 { 386 pmaGetTotalMemory(&pHeap->pmaObject, &bytesTotal); 387 NV_ASSERT(NvU64_HI32(bytesTotal >> 10) == 0); 388 data = NvU64_LO32(bytesTotal >> 10); 389 } 390 else 391 { 392 NvU64 size; 393 394 heapGetUsableSize(pHeap, &size); 395 NV_ASSERT(NvU64_HI32(size >> 10) == 0); 396 data = NvU64_LO32(size >> 10); 397 } 398 data -= pMemsysConfig->fbOverrideStartKb; 399 break; 400 } 401 case NV2080_CTRL_FB_INFO_INDEX_HEAP_START: 402 { 403 if (pMemoryPartitionHeap != NULL) 404 { 405 if (bIsPmaEnabled) 406 { 407 pmaGetLargestFree(&pHeap->pmaObject, &largestFree, &heapBase, &largestOffset); 408 } 409 else 410 { 411 status = heapInfo(pHeap, &bytesFree, &bytesTotal, &heapBase, 412 &largestOffset, &largestFree); 413 } 414 data = NvU64_LO32(heapBase >> 10); 415 } 416 else 417 { 418 const MEMORY_SYSTEM_STATIC_CONFIG *pMemsysConfig = 419 kmemsysGetStaticConfig(pGpu, pKernelMemorySystem); 420 if (pMemsysConfig->fbOverrideStartKb != 0) 421 { 422 data = NvU64_LO32(pMemsysConfig->fbOverrideStartKb); 423 NV_ASSERT(((NvU64) data << 10ULL) == pMemsysConfig->fbOverrideStartKb); 424 } 425 else 426 { 427 // 428 // Returns start of heap in kbytes. This is zero unless 429 // VGA display memory is reserved. 430 // 431 heapGetBase(pHeap, &heapBase); 432 data = NvU64_LO32(heapBase >> 10); 433 NV_ASSERT(((NvU64) data << 10ULL) == heapBase); 434 } 435 } 436 break; 437 } 438 case NV2080_CTRL_FB_INFO_INDEX_HEAP_FREE: 439 { 440 if (bIsClientMIGMonitor || bIsClientMIGProfiler) 441 { 442 bytesFree = 0; 443 444 // 445 // Add free memory across the all valid MIG GPU instances and 446 // the global heap. 447 // 448 // As MIG uses the global heap when memory is not 449 // partitioned, skip getting information from it. 450 // 451 if (kmigmgrIsMIGMemPartitioningEnabled(pGpu, pKernelMIGManager)) 452 { 453 memmgrGetFreeMemoryForAllMIGGPUInstances(pGpu, pMemoryManager, &val); 454 bytesFree = val; 455 } 456 457 if (bIsPmaEnabled) 458 pmaGetFreeMemory(&pHeap->pmaObject, &val); 459 else 460 heapGetFree(pHeap, &val); 461 462 bytesFree += val; 463 464 NV_ASSERT(NvU64_HI32(bytesFree >> 10) == 0); 465 data = NvU64_LO32(bytesFree >> 10); 466 } 467 else if (bIsPmaEnabled) 468 { 469 pmaGetFreeMemory(&pHeap->pmaObject, &bytesFree); 470 471 NV_ASSERT(NvU64_HI32(bytesFree >> 10) == 0); 472 data = NvU64_LO32(bytesFree >> 10); 473 } 474 else 475 { 476 NvU64 size; 477 478 heapGetFree(pHeap, &size); 479 NV_ASSERT(NvU64_HI32(size >> 10) == 0); 480 data = NvU64_LO32(size >> 10); 481 } 482 break; 483 } 484 485 case NV2080_CTRL_FB_INFO_INDEX_VISTA_RESERVED_HEAP_SIZE: 486 { 487 // 488 // If PMA is enabled, ideally we wouldn't have any reserved heap but UVM vidheapctrl 489 // allocations are not accounted for by KMD. RM will reserve it. 490 // 491 if (bIsPmaEnabled) 492 { 493 if (pMemoryPartitionHeap != NULL) 494 { 495 data = 0; 496 break; 497 } 498 499 NvU64 uvmReserveMem = 0; 500 memmgrCalcReservedFbSpaceForUVM_HAL(pGpu, pMemoryManager, &uvmReserveMem); 501 // Ceil bytes and return the # of KB 502 data = NvU64_LO32(NV_CEIL(uvmReserveMem, 1024)); 503 } 504 else 505 { 506 memmgrCalcReservedFbSpace(pGpu, pMemoryManager); 507 // heap size in kbytes 508 data = memmgrGetReservedHeapSizeMb_HAL(pGpu, pMemoryManager) << 10; 509 } 510 break; 511 } 512 513 case NV2080_CTRL_FB_INFO_INDEX_MAPPABLE_HEAP_SIZE: 514 { 515 const MEMORY_SYSTEM_STATIC_CONFIG *pMemsysConfig = 516 kmemsysGetStaticConfig(pGpu, pKernelMemorySystem); 517 if (bIsPmaEnabled) 518 { 519 NvU32 heapSizeKb; 520 521 pmaGetTotalMemory(&pHeap->pmaObject, &bytesTotal); 522 NV_ASSERT(NvU64_HI32(bytesTotal >> 10) == 0); 523 heapSizeKb = NvU64_LO32(bytesTotal >> 10); 524 525 data = memmgrGetMappableRamSizeMb(pMemoryManager) << 10; 526 if (data > heapSizeKb) 527 data = heapSizeKb; 528 } 529 else 530 { 531 NvU64 size; 532 NvU32 heapSizeKb; 533 534 heapGetSize(pHeap, &size); 535 NV_ASSERT(NvU64_HI32(size >> 10) == 0); 536 heapSizeKb = NvU64_LO32(size >> 10); 537 538 data = memmgrGetMappableRamSizeMb(pMemoryManager) << 10; 539 if (data > heapSizeKb) 540 data = heapSizeKb; 541 } 542 data -= pMemsysConfig->fbOverrideStartKb; 543 break; 544 } 545 case NV2080_CTRL_FB_INFO_INDEX_BANK_COUNT: 546 { 547 data = 1; 548 break; 549 } 550 case NV2080_CTRL_FB_INFO_INDEX_OVERLAY_OFFSET_ADJUSTMENT: 551 { 552 data = 0; 553 break; 554 } 555 case NV2080_CTRL_FB_INFO_INDEX_FB_TAX_SIZE_KB: 556 { 557 bytesTotal = memmgrGetFbTaxSize_HAL(pGpu, pMemoryManager); 558 data = NvU64_LO32(bytesTotal >> 10); 559 break; 560 } 561 case NV2080_CTRL_FB_INFO_INDEX_HEAP_BASE_KB: 562 { 563 if (bIsPmaEnabled) 564 { 565 pmaGetLargestFree(&pHeap->pmaObject, &largestFree, &heapBase, &largestOffset); 566 } 567 else 568 { 569 status = heapInfo(pHeap, &bytesFree, &bytesTotal, &heapBase, 570 &largestOffset, &largestFree); 571 } 572 573 data = NvU64_LO32(heapBase >> 10); 574 break; 575 } 576 case NV2080_CTRL_FB_INFO_INDEX_LARGEST_FREE_REGION_SIZE_KB: 577 { 578 if (bIsPmaEnabled) 579 { 580 pmaGetLargestFree(&pHeap->pmaObject, &largestFree, &heapBase, &largestOffset); 581 } 582 else 583 { 584 status = heapInfo(pHeap, &bytesFree, &bytesTotal, &heapBase, 585 &largestOffset, &largestFree); 586 } 587 588 data = NvU64_LO32(largestFree >> 10); 589 break; 590 } 591 case NV2080_CTRL_FB_INFO_INDEX_LARGEST_FREE_REGION_BASE_KB: 592 { 593 if (bIsPmaEnabled) 594 { 595 pmaGetLargestFree(&pHeap->pmaObject, &largestFree, &heapBase, &largestOffset); 596 } 597 else 598 { 599 status = heapInfo(pHeap, &bytesFree, &bytesTotal, &heapBase, 600 &largestOffset, &largestFree); 601 } 602 603 data = NvU64_LO32(largestOffset >> 10); 604 break; 605 } 606 case NV2080_CTRL_FB_INFO_INDEX_RAM_LOCATION: 607 { 608 data = NV2080_CTRL_FB_INFO_RAM_LOCATION_GPU_DEDICATED; 609 break; 610 } 611 case NV2080_CTRL_FB_INFO_INDEX_FB_IS_BROKEN: 612 { 613 data = (pGpu->getProperty(pGpu, PDB_PROP_GPU_BROKEN_FB) && 614 !pGpu->getProperty(pGpu, PDB_PROP_GPU_ZERO_FB)) ? 1 : 0; 615 break; 616 } 617 case NV2080_CTRL_FB_INFO_INDEX_L2CACHE_ONLY_MODE: 618 { 619 data = gpuIsCacheOnlyModeEnabled(pGpu) ? 1 : 0; 620 break; 621 } 622 623 case NV2080_CTRL_FB_INFO_INDEX_SMOOTHDISP_RSVD_BAR1_SIZE: 624 { 625 data = pGpu->uefiScanoutSurfaceSizeInMB; 626 break; 627 } 628 629 case NV2080_CTRL_FB_INFO_INDEX_HEAP_OFFLINE_SIZE: 630 { 631 data = pHeap->dynamicBlacklistSize; 632 break; 633 } 634 case NV2080_CTRL_FB_INFO_INDEX_1TO1_COMPTAG_ENABLED: 635 { 636 const MEMORY_SYSTEM_STATIC_CONFIG *pMemorySystemConfig = kmemsysGetStaticConfig(pGpu, pKernelMemorySystem); 637 data = (pMemorySystemConfig->bOneToOneComptagLineAllocation) ? 1 : 0; 638 break; 639 } 640 641 case NV2080_CTRL_FB_INFO_INDEX_SUSPEND_RESUME_RSVD_SIZE: 642 { 643 NvU64 rsvdSize = memmgrGetRsvdSizeForSr_HAL(pGpu, pMemoryManager); 644 NV_ASSERT(NvU64_HI32(rsvdSize) == 0); 645 data = NvU64_LO32(rsvdSize); 646 break; 647 } 648 case NV2080_CTRL_FB_INFO_INDEX_ALLOW_PAGE_RETIREMENT: 649 { 650 data = pGpu->getProperty(pGpu, PDB_PROP_GPU_ALLOW_PAGE_RETIREMENT) ? 1 : 0; 651 break; 652 } 653 case NV2080_CTRL_FB_INFO_POISON_FUSE_ENABLED: 654 { 655 data = gpuIsGlobalPoisonFuseEnabled(pGpu) ? 1 : 0; 656 break; 657 } 658 case NV2080_CTRL_FB_INFO_FBPA_ECC_ENABLED: 659 { 660 const MEMORY_SYSTEM_STATIC_CONFIG *pMemorySystemConfig = 661 kmemsysGetStaticConfig(pGpu, GPU_GET_KERNEL_MEMORY_SYSTEM(pGpu)); 662 data = (pMemorySystemConfig->bEnabledEccFBPA) ? 1: 0; 663 break; 664 } 665 case NV2080_CTRL_FB_INFO_DYNAMIC_PAGE_OFFLINING_ENABLED: 666 { 667 data = pMemoryManager->bEnableDynamicPageOfflining ? 1 : 0; 668 break; 669 } 670 case NV2080_CTRL_FB_INFO_INDEX_FORCED_BAR1_64KB_MAPPING_ENABLED: 671 { 672 KernelBus *pKernelBus = GPU_GET_KERNEL_BUS(pGpu); 673 data = kbusIsBar1Force64KBMappingEnabled(pKernelBus); 674 break; 675 } 676 case NV2080_CTRL_FB_INFO_INDEX_P2P_MAILBOX_SIZE: 677 { 678 KernelBus *pKernelBus = GPU_GET_KERNEL_BUS(pGpu); 679 data = 0; 680 if (kbusIsP2pMailboxClientAllocated(pKernelBus)) 681 kbusGetP2PMailboxAttributes_HAL(pGpu, pKernelBus, &data, NULL, NULL); 682 break; 683 } 684 case NV2080_CTRL_FB_INFO_INDEX_P2P_MAILBOX_ALIGNMENT: 685 { 686 KernelBus *pKernelBus = GPU_GET_KERNEL_BUS(pGpu); 687 data = 0; 688 if (kbusIsP2pMailboxClientAllocated(pKernelBus)) 689 kbusGetP2PMailboxAttributes_HAL(pGpu, pKernelBus, NULL, &data, NULL); 690 break; 691 } 692 case NV2080_CTRL_FB_INFO_INDEX_P2P_MAILBOX_BAR1_MAX_OFFSET_64KB: 693 { 694 KernelBus *pKernelBus = GPU_GET_KERNEL_BUS(pGpu); 695 data = 0; 696 if (kbusIsP2pMailboxClientAllocated(pKernelBus)) 697 kbusGetP2PMailboxAttributes_HAL(pGpu, pKernelBus, NULL, NULL, &data); 698 break; 699 } 700 default: 701 { 702 data = 0; 703 status = NV_ERR_INVALID_ARGUMENT; 704 break; 705 } 706 } 707 708 if (status != NV_OK) 709 break; 710 // save off data value 711 pFbInfos[i].data = data; 712 } 713 714 return status; 715 } 716 717 // 718 // subdeviceCtrlCmdFbGetInfo 719 // 720 // Lock Requirements: 721 // Assert that API and Gpus lock held on entry 722 // 723 NV_STATUS 724 subdeviceCtrlCmdFbGetInfo_IMPL 725 ( 726 Subdevice *pSubdevice, 727 NV2080_CTRL_FB_GET_INFO_PARAMS *pFbInfoParams 728 ) 729 { 730 OBJGPU *pGpu = GPU_RES_GET_GPU(pSubdevice); 731 NvHandle hClient = RES_GET_CLIENT_HANDLE(pSubdevice); 732 NvHandle hObject = RES_GET_HANDLE(pSubdevice); 733 734 LOCK_ASSERT_AND_RETURN(rmapiLockIsOwner() && rmDeviceGpuLockIsOwner(pGpu->gpuInstance)); 735 736 if ((pFbInfoParams->fbInfoListSize == 0) || 737 (NvP64_VALUE(pFbInfoParams->fbInfoList) == NULL)) 738 { 739 return NV_ERR_INVALID_ARGUMENT; 740 } 741 742 return _fbGetFbInfos(pGpu, hClient, hObject, NvP64_VALUE(pFbInfoParams->fbInfoList), pFbInfoParams->fbInfoListSize); 743 } 744 745 // 746 // subdeviceCtrlCmdFbGetInfoV2 747 // 748 // Lock Requirements: 749 // Assert that API and Gpus lock held on entry 750 // 751 NV_STATUS 752 subdeviceCtrlCmdFbGetInfoV2_IMPL 753 ( 754 Subdevice *pSubdevice, 755 NV2080_CTRL_FB_GET_INFO_V2_PARAMS *pFbInfoParams 756 ) 757 { 758 OBJGPU *pGpu = GPU_RES_GET_GPU(pSubdevice); 759 NvHandle hClient = RES_GET_CLIENT_HANDLE(pSubdevice); 760 NvHandle hObject = RES_GET_HANDLE(pSubdevice); 761 762 LOCK_ASSERT_AND_RETURN(rmapiLockIsOwner() && rmDeviceGpuLockIsOwner(pGpu->gpuInstance)); 763 764 if ((pFbInfoParams->fbInfoListSize > NV2080_CTRL_FB_INFO_MAX_LIST_SIZE) || 765 (pFbInfoParams->fbInfoListSize == 0)) 766 { 767 return NV_ERR_INVALID_ARGUMENT; 768 } 769 770 return _fbGetFbInfos(pGpu, hClient, hObject, pFbInfoParams->fbInfoList, pFbInfoParams->fbInfoListSize); 771 } 772 773 // 774 // subdeviceCtrlCmdFbGetCarveoutAddressInfo 775 // 776 // Lock Requirements: 777 // Assert that API and GPUs lock held on entry 778 // 779 NV_STATUS 780 subdeviceCtrlCmdFbGetCarveoutAddressInfo_IMPL 781 ( 782 Subdevice *pSubdevice, 783 NV2080_CTRL_FB_GET_SYSTEM_CARVEOUT_ADDRESS_SPACE_INFO *pParams 784 ) 785 { 786 787 LOCK_ASSERT_AND_RETURN(rmapiLockIsOwner() && rmGpuLockIsOwner()); 788 789 pParams->StartAddr = 0x0; 790 pParams->SpaceSize = 0x0; 791 792 return NV_ERR_GENERIC; 793 } 794 795 // 796 // subdeviceCtrlCmdFbSetGpuCacheAllocPolicy 797 // 798 // Lock Requirements: 799 // Assert that GPUs lock held on entry 800 // Called from SW method w/o API lock 801 // 802 NV_STATUS 803 subdeviceCtrlCmdFbSetGpuCacheAllocPolicy_IMPL 804 ( 805 Subdevice *pSubdevice, 806 NV2080_CTRL_FB_GPU_CACHE_ALLOC_POLICY_PARAMS *pParams 807 ) 808 { 809 LOCK_ASSERT_AND_RETURN(rmGpuLockIsOwner()); 810 811 // Map engine to FBBA client 812 return NV_ERR_NOT_SUPPORTED; 813 } 814 815 // 816 // subdeviceCtrlCmdFbGetGpuCacheAllocPolicy 817 // 818 // Lock Requirements: 819 // Assert that API and GPUs lock held on entry 820 // 821 NV_STATUS 822 subdeviceCtrlCmdFbGetGpuCacheAllocPolicy_IMPL 823 ( 824 Subdevice *pSubdevice, 825 NV2080_CTRL_FB_GPU_CACHE_ALLOC_POLICY_PARAMS *pGpuCacheAllocPolicyParams 826 ) 827 { 828 829 NV_STATUS status = NV_ERR_NOT_SUPPORTED; 830 LOCK_ASSERT_AND_RETURN(rmapiLockIsOwner() && rmGpuLockIsOwner()); 831 832 pGpuCacheAllocPolicyParams->allocPolicy = 0; 833 834 NV_PRINTF(LEVEL_ERROR, "Failed to read Client reads ALLOC policy\n"); 835 return status; 836 } 837 838 // 839 // subdeviceCtrlCmdFbSetGpuCacheAllocPolicyV2 840 // 841 // Lock Requirements: 842 // Assert that GPUs lock held on entry 843 // Called from SW method w/o API lock 844 // 845 NV_STATUS 846 subdeviceCtrlCmdFbSetGpuCacheAllocPolicyV2_IMPL 847 ( 848 Subdevice *pSubdevice, 849 NV2080_CTRL_FB_GPU_CACHE_ALLOC_POLICY_V2_PARAMS *pParams 850 ) 851 { 852 CALL_CONTEXT *pCallContext = resservGetTlsCallContext(); 853 RmCtrlParams *pRmCtrlParams = pCallContext->pControlParams; 854 NV_STATUS status = NV_ERR_NOT_SUPPORTED; 855 856 // Bug 724186 -- Skip this check for deferred API 857 LOCK_ASSERT_AND_RETURN(pRmCtrlParams->bDeferredApi || rmGpuLockIsOwner()); 858 859 NV_PRINTF(LEVEL_ERROR, "Failed to set alloc policy\n"); 860 return status; 861 } 862 863 // 864 // subdeviceCtrlCmdFbGetGpuCacheAllocPolicyV2 865 // 866 // Lock Requirements: 867 // Assert that API and GPUs lock held on entry 868 // 869 NV_STATUS 870 subdeviceCtrlCmdFbGetGpuCacheAllocPolicyV2_IMPL 871 ( 872 Subdevice *pSubdevice, 873 NV2080_CTRL_FB_GPU_CACHE_ALLOC_POLICY_V2_PARAMS *pParams 874 ) 875 { 876 NV_STATUS status = NV_ERR_NOT_SUPPORTED; 877 878 NV_ASSERT_OR_RETURN(rmapiLockIsOwner() && rmGpuLockIsOwner(), NV_ERR_INVALID_LOCK_STATE); 879 880 NV_PRINTF(LEVEL_ERROR, "Failed to get alloc policy.\n"); 881 return status; 882 } 883 884 // 885 // subdeviceCtrlCmdFbGetCliManagedOfflinedPages 886 // 887 // Lock Requirements: 888 // Assert that API and Gpus lock held on entry 889 // 890 891 NV_STATUS 892 subdeviceCtrlCmdFbGetCliManagedOfflinedPages_IMPL 893 ( 894 Subdevice *pSubdevice, 895 NV2080_CTRL_FB_GET_CLI_MANAGED_OFFLINED_PAGES_PARAMS *pOsOfflinedParams 896 ) 897 { 898 OBJGPU *pGpu = GPU_RES_GET_GPU(pSubdevice); 899 Heap *pHeap = GPU_GET_HEAP(pGpu); 900 MemoryManager *pMemoryManager = GPU_GET_MEMORY_MANAGER(pGpu); 901 BLACKLIST_CHUNK *pBlacklistChunks = pHeap->blackList.pBlacklistChunks; 902 NvU64 pageAddress; 903 NvU32 i; 904 NvU32 osBlackListCount = 0; 905 NvU32 chunk; 906 NvU64 chunks[NV2080_CTRL_FB_OFFLINED_PAGES_MAX_PAGES]; 907 NvU32 pageSize; 908 NvU32 numChunks = 0; 909 910 LOCK_ASSERT_AND_RETURN(rmapiLockIsOwner() && rmGpuLockIsOwner()); 911 if (!IsSLIEnabled(pGpu)) 912 { 913 if (memmgrIsPmaInitialized(pMemoryManager)) 914 { 915 // If PMA is enabled Client pages are located here. 916 pmaGetClientBlacklistedPages(&pHeap->pmaObject, chunks, &pageSize, &numChunks); 917 918 NV_ASSERT(numChunks <= NV2080_CTRL_FB_OFFLINED_PAGES_MAX_PAGES); 919 920 for (chunk = 0; chunk < numChunks; chunk++) 921 { 922 pOsOfflinedParams->offlinedPages[chunk] = (NvU32)(chunks[chunk] >> RM_PAGE_SHIFT); 923 } 924 pOsOfflinedParams->validEntries = numChunks; 925 pOsOfflinedParams->pageSize = pageSize; 926 } 927 else 928 { 929 // Iterate over the heap blacklist array to get the OS blacklisted regions 930 for (i = 0; i < pHeap->blackList.count; i++) 931 { 932 // Extract only the globally excluded page offsets 933 if (!pBlacklistChunks[i].bIsValid) 934 { 935 pageAddress = pBlacklistChunks[i].physOffset; 936 pOsOfflinedParams->offlinedPages[osBlackListCount] = (NvU32) (pageAddress >> RM_PAGE_SHIFT); 937 osBlackListCount++; 938 } 939 } 940 pOsOfflinedParams->validEntries = osBlackListCount; 941 pOsOfflinedParams->pageSize = RM_PAGE_SIZE; 942 } 943 return NV_OK; 944 } 945 else 946 return NV_ERR_NOT_SUPPORTED; 947 } 948 949 /*! 950 * @brief This call can be used to update the NUMA status. 951 * 952 * Lock Requirements: 953 * Assert that API and GPUs lock held on entry 954 * 955 * @param[in] pSubdevice Subdevice 956 * @param[in] pParams pointer to control parameters 957 * 958 * @return NV_OK When successful 959 * NV_ERR_INVALID_STATE Otherwise 960 */ 961 NV_STATUS 962 subdeviceCtrlCmdFbUpdateNumaStatus_IMPL 963 ( 964 Subdevice *pSubdevice, 965 NV2080_CTRL_FB_UPDATE_NUMA_STATUS_PARAMS *pParams 966 ) 967 { 968 OBJGPU *pGpu = GPU_RES_GET_GPU(pSubdevice); 969 KernelMemorySystem *pKernelMemorySystem = GPU_GET_KERNEL_MEMORY_SYSTEM(pGpu); 970 Heap *pHeap = GPU_GET_HEAP(pGpu); 971 PMA *pPma = &pHeap->pmaObject; 972 NV_STATUS status = NV_OK; 973 974 if (!RMCFG_FEATURE_PMA) 975 return NV_ERR_NOT_SUPPORTED; 976 977 LOCK_ASSERT_AND_RETURN(rmapiLockIsOwner() && rmGpuLockIsOwner()); 978 979 if (pParams->bOnline) 980 { 981 status = pmaNumaOnlined(pPma, pGpu->numaNodeId, 982 pKernelMemorySystem->coherentCpuFbBase, 983 pKernelMemorySystem->numaOnlineSize); 984 } 985 else 986 { 987 pmaNumaOfflined(pPma); 988 } 989 990 return status; 991 } 992 993 /* 994 * @brief This call can be used to get NUMA related information. 995 * 996 * Lock Requirements: 997 * Assert that API and GPUs lock held on entry 998 * 999 * @param[in] pSubdevice Subdevice 1000 * @param[in] pParams pointer to control parameters 1001 * 1002 * @return NV_OK When successful 1003 * NV_ERR_INVALID_STATE Otherwise 1004 */ 1005 NV_STATUS 1006 subdeviceCtrlCmdFbGetNumaInfo_IMPL 1007 ( 1008 Subdevice *pSubdevice, 1009 NV2080_CTRL_FB_GET_NUMA_INFO_PARAMS *pParams 1010 ) 1011 { 1012 OBJGPU *pGpu = GPU_RES_GET_GPU(pSubdevice); 1013 KernelMemorySystem *pKernelMemorySystem = GPU_GET_KERNEL_MEMORY_SYSTEM(pGpu); 1014 MemoryManager *pMemoryManager = GPU_GET_MEMORY_MANAGER(pGpu); 1015 BLACKLIST_ADDRESS *pBlAddrs; 1016 NvU32 numaOfflineIdx = 0; 1017 NvU32 idx; 1018 NV_STATUS status; 1019 NvU32 count; 1020 const MEMORY_SYSTEM_STATIC_CONFIG *pMemorySystemConfig = 1021 kmemsysGetStaticConfig(pGpu, pKernelMemorySystem); 1022 1023 LOCK_ASSERT_AND_RETURN(rmapiLockIsOwner() && rmGpuLockIsOwner()); 1024 1025 if (pParams->numaOfflineAddressesCount > 1026 NV_ARRAY_ELEMENTS(pParams->numaOfflineAddresses)) 1027 { 1028 return NV_ERR_INVALID_ARGUMENT; 1029 } 1030 1031 pParams->numaNodeId = pGpu->numaNodeId; 1032 pParams->numaMemAddr = pKernelMemorySystem->coherentCpuFbBase + pKernelMemorySystem->numaOnlineBase; 1033 pParams->numaMemSize = pKernelMemorySystem->numaOnlineSize; 1034 1035 if (pParams->numaOfflineAddressesCount == 0) 1036 { 1037 return NV_OK; 1038 } 1039 1040 if (!(pGpu->getProperty(pGpu, PDB_PROP_GPU_ALLOW_PAGE_RETIREMENT) && 1041 gpuCheckPageRetirementSupport_HAL(pGpu))) 1042 { 1043 pParams->numaOfflineAddressesCount = 0; 1044 return NV_OK; 1045 } 1046 1047 count = pMemorySystemConfig->maximumBlacklistPages; 1048 pBlAddrs = portMemAllocNonPaged(sizeof(BLACKLIST_ADDRESS) * count); 1049 if (pBlAddrs == NULL) 1050 { 1051 return NV_ERR_NO_MEMORY; 1052 } 1053 1054 status = memmgrGetBlackListPages_HAL(pGpu, pMemoryManager, pBlAddrs, &count); 1055 NV_ASSERT(status != NV_ERR_BUFFER_TOO_SMALL); 1056 1057 if(status == NV_OK) 1058 { 1059 for (idx = 0; idx < count; idx++) 1060 { 1061 NvU64 offset = pBlAddrs[idx].address; 1062 1063 if (numaOfflineIdx >= pParams->numaOfflineAddressesCount) 1064 { 1065 status = NV_ERR_BUFFER_TOO_SMALL; 1066 break; 1067 } 1068 1069 // Only tell the caller about Offline pages in the NUMA region. 1070 if (offset < pParams->numaMemSize) 1071 { 1072 pParams->numaOfflineAddresses[numaOfflineIdx++] = pParams->numaMemAddr + offset; 1073 } 1074 else 1075 { 1076 NV_PRINTF(LEVEL_INFO, "retired page address 0x%llx not in NUMA region\n", 1077 offset); 1078 } 1079 } 1080 } 1081 else 1082 { 1083 // No offlined pages or failure to read offlined addresses. 1084 status = NV_OK; 1085 } 1086 1087 pParams->numaOfflineAddressesCount = numaOfflineIdx; 1088 1089 portMemFree(pBlAddrs); 1090 1091 return status; 1092 } 1093 1094 NV_STATUS 1095 subdeviceCtrlCmdFbSetZbcReferenced_IMPL 1096 ( 1097 Subdevice *pSubdevice, 1098 NV2080_CTRL_INTERNAL_MEMSYS_SET_ZBC_REFERENCED_PARAMS *pParams 1099 ) 1100 { 1101 OBJGPU *pGpu = GPU_RES_GET_GPU(pSubdevice); 1102 CALL_CONTEXT *pCallContext = resservGetTlsCallContext(); 1103 NvU32 gfid; 1104 NV_STATUS status = NV_OK; 1105 1106 NV_ASSERT_OK_OR_RETURN(vgpuGetCallingContextGfid(pGpu, &gfid)); 1107 1108 NV_CHECK_OR_RETURN(LEVEL_ERROR, IS_GFID_VF(gfid) || pCallContext->secInfo.privLevel >= RS_PRIV_LEVEL_KERNEL, NV_ERR_INSUFFICIENT_PERMISSIONS); 1109 1110 if (IS_VIRTUAL(pGpu) || IS_GSP_CLIENT(pGpu)) 1111 { 1112 RmCtrlParams *pRmCtrlParams = pCallContext->pControlParams; 1113 1114 NV_RM_RPC_CONTROL(pGpu, 1115 pRmCtrlParams->hClient, 1116 pRmCtrlParams->hObject, 1117 pRmCtrlParams->cmd, 1118 pRmCtrlParams->pParams, 1119 pRmCtrlParams->paramsSize, 1120 status); 1121 1122 return status; 1123 } 1124 1125 return status; 1126 } 1127 1128 /*! 1129 * @brief This call can be used to flush L2 followed by FB or 1130 * just the FB. 1131 * 1132 * If L2 ops are needed, either _INVALIDATE or _WRITE_BACK 1133 * or both flags set to _YES is required. Specifying both 1134 * to _YES implies EVICT. 1135 * 1136 * If only the FB flush is needed, only the 1137 * _APERTURE and _FB_FLUSH_YES are needed. 1138 * 1139 * If only L2 ops are needed (i.e. no FB flush following 1140 * it), _FB_FLUSH_NO is needed in addition to the other 1141 * L2 ops flags. 1142 * 1143 * Lock Requirements: 1144 * Assert that API and GPUs lock held on entry 1145 * 1146 * @param[in] pSubdevice Subdevice 1147 * @param[in] pCacheFlushParams Various flush flags 1148 * 1149 */ 1150 NV_STATUS 1151 subdeviceCtrlCmdFbFlushGpuCache_IMPL 1152 ( 1153 Subdevice *pSubdevice, 1154 NV2080_CTRL_FB_FLUSH_GPU_CACHE_PARAMS *pCacheFlushParams 1155 ) 1156 { 1157 OBJGPU *pGpu = GPU_RES_GET_GPU(pSubdevice); 1158 KernelMemorySystem *pKernelMemorySystem = GPU_GET_KERNEL_MEMORY_SYSTEM(pGpu); 1159 NV_STATUS status = NV_OK; 1160 FB_CACHE_MEMTYPE memType = FB_CACHE_MEM_UNDEFINED; 1161 FB_CACHE_OP cacheOp = FB_CACHE_OP_UNDEFINED; 1162 KernelBus *pKernelBus = GPU_GET_KERNEL_BUS(pGpu); 1163 NvBool bWriteback = NV_FALSE; 1164 NvBool bInvalidate = NV_FALSE; 1165 1166 LOCK_ASSERT_AND_RETURN(rmapiLockIsOwner() && rmGpuLockIsOwner()); 1167 1168 // Either WriteBack or Invalidate are required for Cache Ops 1169 if (FLD_TEST_DRF(2080, _CTRL_FB_FLUSH_GPU_CACHE_FLAGS, _WRITE_BACK, 1170 _YES, pCacheFlushParams->flags)) 1171 { 1172 bWriteback = NV_TRUE; 1173 } 1174 if (FLD_TEST_DRF(2080, _CTRL_FB_FLUSH_GPU_CACHE_FLAGS, _INVALIDATE, 1175 _YES, pCacheFlushParams->flags)) 1176 { 1177 bInvalidate = NV_TRUE; 1178 } 1179 1180 if (bWriteback || bInvalidate ) 1181 { 1182 // Cache Ops Path 1183 1184 switch (DRF_VAL(2080, _CTRL_FB_FLUSH_GPU_CACHE_FLAGS, _APERTURE, 1185 pCacheFlushParams->flags)) 1186 { 1187 case NV2080_CTRL_FB_FLUSH_GPU_CACHE_FLAGS_APERTURE_VIDEO_MEMORY: 1188 memType = FB_CACHE_VIDEO_MEMORY; 1189 break; 1190 case NV2080_CTRL_FB_FLUSH_GPU_CACHE_FLAGS_APERTURE_SYSTEM_MEMORY: 1191 memType = FB_CACHE_SYSTEM_MEMORY; 1192 break; 1193 case NV2080_CTRL_FB_FLUSH_GPU_CACHE_FLAGS_APERTURE_PEER_MEMORY: 1194 memType = FB_CACHE_PEER_MEMORY; 1195 break; 1196 default: 1197 NV_PRINTF(LEVEL_ERROR, "Invalid aperture.\n"); 1198 return NV_ERR_INVALID_ARGUMENT; 1199 } 1200 1201 if (bWriteback && bInvalidate) 1202 { 1203 cacheOp = FB_CACHE_EVICT; 1204 } 1205 else if (!bWriteback && bInvalidate) 1206 { 1207 cacheOp = FB_CACHE_INVALIDATE; 1208 } 1209 else if (bWriteback && !bInvalidate) 1210 { 1211 cacheOp = FB_CACHE_WRITEBACK; 1212 } 1213 else 1214 { 1215 NV_PRINTF(LEVEL_ERROR, 1216 "Must specify at least one of WRITE_BACK or INVALIDATE\n"); 1217 return NV_ERR_INVALID_ARGUMENT; 1218 } 1219 1220 switch (DRF_VAL(2080, _CTRL_FB_FLUSH_GPU_CACHE_FLAGS, _FLUSH_MODE, 1221 pCacheFlushParams->flags)) 1222 { 1223 case NV2080_CTRL_FB_FLUSH_GPU_CACHE_FLAGS_FLUSH_MODE_ADDRESS_ARRAY: 1224 if ((pCacheFlushParams->addressArraySize == 0) || 1225 (pCacheFlushParams->addressArraySize > 1226 NV2080_CTRL_FB_FLUSH_GPU_CACHE_MAX_ADDRESSES)) 1227 { 1228 NV_PRINTF(LEVEL_ERROR, "Invalid array size (0x%x)\n", 1229 pCacheFlushParams->addressArraySize); 1230 status = NV_ERR_INVALID_ARGUMENT; 1231 break; 1232 } 1233 1234 if(pCacheFlushParams->memBlockSizeBytes == 0) 1235 { 1236 NV_PRINTF(LEVEL_ERROR, "Invalid memBlock size (0x%llx)\n", 1237 pCacheFlushParams->memBlockSizeBytes); 1238 status = NV_ERR_INVALID_ARGUMENT; 1239 break; 1240 } 1241 1242 status = NV_ERR_GENERIC; 1243 break; 1244 case NV2080_CTRL_FB_FLUSH_GPU_CACHE_FLAGS_FLUSH_MODE_FULL_CACHE: 1245 status = kmemsysCacheOp_HAL(pGpu, pKernelMemorySystem, NULL, memType, cacheOp); 1246 break; 1247 default: 1248 NV_PRINTF(LEVEL_ERROR, "Invalid FLUSH_MODE 0x%x\n", 1249 DRF_VAL(2080, _CTRL_FB_FLUSH_GPU_CACHE_FLAGS, _FLUSH_MODE, pCacheFlushParams->flags)); 1250 return NV_ERR_INVALID_ARGUMENT; 1251 } 1252 } 1253 1254 // FB Flush 1255 if (FLD_TEST_DRF(2080, _CTRL_FB_FLUSH_GPU_CACHE_FLAGS, _FB_FLUSH, 1256 _YES, pCacheFlushParams->flags)) 1257 { 1258 NV_CHECK_OK_OR_CAPTURE_FIRST_ERROR(status, LEVEL_ERROR, 1259 kbusFlush_HAL(pGpu, pKernelBus, BUS_FLUSH_VIDEO_MEMORY)); 1260 } 1261 1262 return status; 1263 } 1264