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