1 /* 2 * SPDX-FileCopyrightText: Copyright (c) 2018-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 "mem_mgr_internal.h" 25 #include "mem_mgr/phys_mem.h" 26 #include "os/os.h" 27 #include "vgpu/rpc.h" 28 #include "gpu/mem_mgr/mem_desc.h" 29 #include "gpu/mmu/kern_gmmu.h" 30 #include "mem_mgr/mem.h" 31 #include "gpu/mem_mgr/mem_mgr.h" 32 #include "gpu/mem_mgr/heap.h" 33 #include "gpu/mem_sys/kern_mem_sys.h" 34 #include "gpu/bus/kern_bus.h" 35 #include "gpu/device/device.h" 36 #include "rmapi/client.h" 37 #include "virtualization/hypervisor/hypervisor.h" 38 39 #include "class/cl0040.h" // NV01_MEMORY_LOCAL_USER 40 #include "class/cl00c2.h" // NV01_MEMORY_LOCAL_PHYSICAL 41 42 NV_STATUS 43 physmemConstruct_IMPL 44 ( 45 PhysicalMemory *pPhysicalMemory, 46 CALL_CONTEXT *pCallContext, 47 RS_RES_ALLOC_PARAMS_INTERNAL *pParams 48 ) 49 { 50 NV_PHYSICAL_MEMORY_ALLOCATION_PARAMS *pAllocParams; 51 NV_STATUS status = NV_OK; 52 NvHandle hClient = pCallContext->pClient->hClient; 53 NvHandle hParent = pCallContext->pResourceRef->pParentRef->hResource; 54 NvHandle hMemory = pCallContext->pResourceRef->hResource; 55 Memory *pMemory = staticCast(pPhysicalMemory, Memory); 56 OBJGPU *pGpu = pMemory->pGpu; 57 MemoryManager *pMemoryManager = GPU_GET_MEMORY_MANAGER(pGpu); 58 KernelGmmu *pKernelGmmu = GPU_GET_KERNEL_GMMU(pGpu); 59 MEMORY_DESCRIPTOR *pMemDesc = NULL; 60 Heap *pHeap = MEMORY_MANAGER_GET_HEAP(pMemoryManager); 61 HWRESOURCE_INFO hwResource = {0}; 62 NvU64 heapBase; 63 NvU64 trueLength; 64 NvBool bCompressedKind; 65 NvU32 attr = DRF_DEF(OS32, _ATTR, _PHYSICALITY, _CONTIGUOUS) | 66 DRF_DEF(OS32, _ATTR, _LOCATION, _VIDMEM); 67 NvU32 attr2 = 0; 68 const MEMORY_SYSTEM_STATIC_CONFIG *pMemorySystemConfig = 69 kmemsysGetStaticConfig(pGpu, GPU_GET_KERNEL_MEMORY_SYSTEM(pGpu)); 70 KernelBus *pKernelBus = GPU_GET_KERNEL_BUS(pGpu); 71 72 NV_ASSERT_OR_RETURN(RMCFG_FEATURE_KERNEL_RM, NV_ERR_NOT_SUPPORTED); 73 74 // Copy-construction has already been done by the base Memory class 75 if (RS_IS_COPY_CTOR(pParams)) 76 return NV_OK; 77 78 // 79 // This class does not allocate ANY framebuffer memory. This function 80 // returns a dumb linear mapping to the entire framebuffer. 81 // 82 // The driver client is responsible for calling RmMapMemory() to actually 83 // get mappings when needed. 84 // 85 // 86 87 pAllocParams = pParams->pAllocParams; 88 bCompressedKind = memmgrIsKind_HAL(pMemoryManager, FB_IS_KIND_COMPRESSIBLE, pAllocParams->format); 89 90 heapGetBase(pHeap, &heapBase); 91 heapGetSize(pHeap, &trueLength); 92 pAllocParams->memSize = trueLength; 93 94 switch (pAllocParams->pageSize) 95 { 96 case RM_PAGE_SIZE_512M: 97 NV_ASSERT_OR_RETURN(kgmmuIsPageSize512mbSupported(pKernelGmmu), NV_ERR_INVALID_ARGUMENT); 98 attr |= DRF_DEF(OS32, _ATTR, _PAGE_SIZE, _HUGE); 99 attr2 |= DRF_DEF(OS32, _ATTR2, _PAGE_SIZE_HUGE, _512MB); 100 break; 101 case RM_PAGE_SIZE_HUGE: 102 NV_ASSERT_OR_RETURN(kgmmuIsHugePageSupported(pKernelGmmu), NV_ERR_INVALID_ARGUMENT); 103 attr |= DRF_DEF(OS32, _ATTR, _PAGE_SIZE, _HUGE); 104 attr2 |= DRF_DEF(OS32, _ATTR2, _PAGE_SIZE_HUGE, _2MB); 105 break; 106 default: 107 if (bCompressedKind && kbusIsStaticBar1Enabled(pGpu, pKernelBus)) 108 { 109 NV_ASSERT_OR_RETURN(kgmmuIsHugePageSupported(pKernelGmmu), NV_ERR_INVALID_ARGUMENT); 110 attr |= DRF_DEF(OS32, _ATTR, _PAGE_SIZE, _HUGE); 111 attr2 |= DRF_DEF(OS32, _ATTR2, _PAGE_SIZE_HUGE, _2MB); 112 113 NV_PRINTF(LEVEL_INFO, 114 "Default to use 2MB page size on this compressed vidmem for the static bar1\n"); 115 } 116 else 117 { 118 attr |= DRF_DEF(OS32, _ATTR, _PAGE_SIZE, _BIG); 119 } 120 break; 121 } 122 123 if (bCompressedKind) 124 { 125 FB_ALLOC_INFO FbAllocInfo = {0}; 126 FB_ALLOC_PAGE_FORMAT fbAllocPageFormat = {0}; 127 128 NV_CHECK_OR_RETURN(LEVEL_ERROR, 129 pMemorySystemConfig->bOneToOneComptagLineAllocation || pMemorySystemConfig->bUseRawModeComptaglineAllocation, 130 NV_ERR_INVALID_ARGUMENT); 131 132 attr |= DRF_DEF(OS32, _ATTR, _ZCULL, _NONE); 133 attr2 |= DRF_DEF(OS32, _ATTR2, _ZBC, _PREFER_NO_ZBC); 134 attr2 |= DRF_DEF(OS32, _ATTR2, _ZBC_SKIP_ZBCREFCOUNT, _YES); 135 136 if (memmgrIsKind_HAL(pMemoryManager, FB_IS_KIND_DISALLOW_PLC, pAllocParams->format)) 137 attr |= DRF_DEF(OS32, _ATTR, _COMPR, _DISABLE_PLC_ANY); 138 else 139 attr |= DRF_DEF(OS32, _ATTR, _COMPR, _REQUIRED); 140 141 FbAllocInfo.pageFormat = &fbAllocPageFormat; 142 FbAllocInfo.hClient = hClient; 143 FbAllocInfo.hDevice = hParent; /* device */ 144 FbAllocInfo.size = trueLength; 145 FbAllocInfo.origSize = trueLength; 146 FbAllocInfo.offset = 0; 147 FbAllocInfo.format = pAllocParams->format; 148 FbAllocInfo.retAttr = attr; 149 FbAllocInfo.retAttr2 = attr2; 150 FbAllocInfo.pageFormat->kind = FbAllocInfo.format; 151 FbAllocInfo.pageFormat->attr = FbAllocInfo.retAttr; 152 FbAllocInfo.pageFormat->attr2 = FbAllocInfo.retAttr2; 153 154 // Fetch RM page size 155 NV_CHECK_OR_RETURN(LEVEL_ERROR, 156 memmgrDeterminePageSize(pMemoryManager, FbAllocInfo.hClient, FbAllocInfo.size, 157 FbAllocInfo.format, FbAllocInfo.pageFormat->flags, 158 &FbAllocInfo.retAttr, &FbAllocInfo.retAttr2) != 0, 159 NV_ERR_INVALID_ARGUMENT); 160 161 // Fetch memory alignment 162 NV_CHECK_OK_OR_RETURN(LEVEL_ERROR, 163 memmgrAllocDetermineAlignment_HAL(pGpu, pMemoryManager, &FbAllocInfo.size, &FbAllocInfo.align, 164 FbAllocInfo.alignPad, FbAllocInfo.pageFormat->flags, 165 FbAllocInfo.retAttr, FbAllocInfo.retAttr2, 0)); 166 167 NV_CHECK_OK_OR_RETURN(LEVEL_ERROR, memmgrAllocHwResources(pGpu, pMemoryManager, &FbAllocInfo)); 168 NV_ASSERT_OR_RETURN(FbAllocInfo.format == pAllocParams->format, NV_ERR_INVALID_ARGUMENT); 169 170 attr = FbAllocInfo.retAttr; 171 attr2 = FbAllocInfo.retAttr2; 172 173 hwResource.attr = FbAllocInfo.retAttr; 174 hwResource.attr2 = FbAllocInfo.retAttr2; 175 hwResource.comprCovg = FbAllocInfo.comprCovg; 176 hwResource.ctagOffset = FbAllocInfo.ctagOffset; 177 hwResource.hwResId = FbAllocInfo.hwResId; 178 } 179 180 status = memCreateMemDesc(pGpu, &pMemDesc, ADDR_FBMEM, 0, trueLength, attr, attr2); 181 182 NV_CHECK_OK_OR_RETURN(LEVEL_ERROR, status); 183 184 memdescDescribe(pMemDesc, ADDR_FBMEM, heapBase, trueLength); 185 186 memdescSetPteKind(pMemDesc, pAllocParams->format); 187 if (bCompressedKind) 188 memdescSetHwResId(pMemDesc, hwResource.hwResId); 189 190 // Track internally as NV01_MEMORY_LOCAL_USER to share regular FB mem code paths 191 NV_CHECK_OK_OR_GOTO(status, LEVEL_ERROR, 192 memConstructCommon(pMemory, NV01_MEMORY_LOCAL_USER, 0, pMemDesc, 0, 193 NULL, attr, attr2, 0, 0, NVOS32_MEM_TAG_NONE, 194 bCompressedKind ? &hwResource : NULL), 195 cleanup_mem); 196 197 if (!IS_GSP_CLIENT(pGpu)) 198 { 199 // 200 // vGPU: 201 // 202 // Since vGPU does all real hardware management in the 203 // host, if we are in guest OS (where IS_VIRTUAL(pGpu) is true), 204 // do an RPC to the host to do the hardware update. 205 // 206 NV_RM_RPC_ALLOC_LOCAL_USER(pGpu, hClient, hParent, hMemory, pMemDesc, trueLength, 207 attr, attr2, pAllocParams->format, status); 208 if (status != NV_OK) 209 { 210 // cleanup on an RPC failure 211 goto cleanup_common; 212 } 213 214 pMemory->bRpcAlloc = NV_TRUE; 215 } 216 217 if (bCompressedKind && kbusIsStaticBar1Enabled(pGpu, pKernelBus)) 218 { 219 NV_CHECK_OK_OR_GOTO(status, LEVEL_ERROR, 220 kbusUpdateStaticBar1VAMapping_HAL(pGpu, pKernelBus, 221 pMemDesc, 0, memdescGetSize(pMemDesc), NV_FALSE), 222 cleanup_rpc); 223 224 memdescSetFlag(pMemDesc, 225 MEMDESC_FLAGS_RESTORE_PTE_KIND_ON_FREE, NV_TRUE); 226 } 227 228 return NV_OK; 229 230 cleanup_rpc: 231 { 232 NV_STATUS rpcstatus = NV_OK;; 233 NV_RM_RPC_FREE(pGpu, hClient, hParent, hMemory, rpcstatus); 234 NV_ASSERT(rpcstatus == NV_OK); 235 } 236 237 cleanup_common: 238 memDestructCommon(pMemory); 239 240 cleanup_mem: 241 memdescDestroy(pMemDesc); 242 243 return status; 244 } 245 246 NvBool 247 physmemCanCopy_IMPL 248 ( 249 PhysicalMemory *pPhysicalMemory 250 ) 251 { 252 return NV_TRUE; 253 } 254