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/standard_mem.h"
26 #include "vgpu/rpc.h"
27 #include "rmapi/client.h"
28 #include "gpu/mem_mgr/mem_mgr.h"
29 #include "virtualization/hypervisor/hypervisor.h"
30 #include "resserv/rs_server.h"
31 #include "rmapi/rs_utils.h"
32 #include "gpu/mem_mgr/heap.h"
33 
stdmemValidateParams(OBJGPU * pGpu,NvHandle hClient,NV_MEMORY_ALLOCATION_PARAMS * pAllocData)34 NV_STATUS stdmemValidateParams
35 (
36     OBJGPU                      *pGpu,
37     NvHandle                     hClient,
38     NV_MEMORY_ALLOCATION_PARAMS *pAllocData
39 )
40 {
41     NvBool         bIso;
42     RS_PRIV_LEVEL  privLevel;
43     CALL_CONTEXT  *pCallContext = resservGetTlsCallContext();
44 
45     NV_ASSERT_OR_RETURN(RMCFG_FEATURE_KERNEL_RM, NV_ERR_NOT_SUPPORTED);
46 
47     NV_ASSERT_OR_RETURN(pCallContext != NULL, NV_ERR_INVALID_STATE);
48     privLevel = pCallContext->secInfo.privLevel;
49 
50     //
51     // Make sure UMD does not impact the internal allocation flags
52     // Do this check right after copy in. RM is free to set these flags later
53     //
54     if ((privLevel < RS_PRIV_LEVEL_KERNEL) &&
55         (pAllocData->internalflags != 0))
56     {
57         return NV_ERR_INVALID_ARGUMENT;
58     }
59 
60     //
61     // These flags don't do anything in this path. No mapping on alloc and
62     // kernel map is controlled by TYPE
63     //
64     pAllocData->flags |= NVOS32_ALLOC_FLAGS_MAP_NOT_REQUIRED;
65     pAllocData->flags &= ~NVOS32_ALLOC_FLAGS_KERNEL_MAPPING_MAP;
66 
67     pAllocData->address = NvP64_NULL;
68 
69     //
70     // Reject any API calls that pass an invalid owner.
71     // Reject any client calls that try to mess with internal RM memory.
72     //
73     if ((pAllocData->owner == 0) ||
74         (pAllocData->owner == 0xFFFFFFFF) ||
75         ((pAllocData->owner >= HEAP_OWNER_RM_SCRATCH_BEGIN) &&
76          (pAllocData->owner <= HEAP_OWNER_RM_SCRATCH_END)))
77     {
78         return NV_ERR_INVALID_OWNER;
79     }
80 
81     bIso = (pAllocData->type == NVOS32_TYPE_PRIMARY) ||
82            (pAllocData->type == NVOS32_TYPE_VIDEO) ||
83            (pAllocData->type == NVOS32_TYPE_CURSOR);
84 
85     //
86     // MM-TODO: If surface requires ISO guarantees, ensure it's of the proper
87     // NVOS32_TYPE. Eventually, we should decouple NVOS32_TYPE from conveying
88     // ISO behavior; RM needs to audit NVOS32_TYPE uses wrt ISO determination.
89     //
90     if (!bIso && FLD_TEST_DRF(OS32, _ATTR2, _ISO, _YES, pAllocData->attr2))
91     {
92         NV_PRINTF(LEVEL_INFO, "type is non-ISO but attributes request ISO!\n");
93         return NV_ERR_INVALID_ARGUMENT;
94     }
95 
96     //
97     // check PAGE_OFFLINING flag for client
98     // If the client is not a ROOT client, then turning PAGE_OFFLINIG OFF is invalid
99     //
100     if (FLD_TEST_DRF(OS32, _ATTR2, _PAGE_OFFLINING, _OFF, pAllocData->attr2))
101     {
102         if (hypervisorIsVgxHyper())
103         {
104             if (!(rmclientIsAdminByHandle(hClient, privLevel) || hypervisorCheckForObjectAccess(hClient)))
105             {
106                 return NV_ERR_INSUFFICIENT_PERMISSIONS;
107             }
108         }
109         else
110         {
111             // if the client requesting is not kernel mode, return early
112 #if defined(DEBUG) || defined(DEVELOP) || defined(NV_VERIF_FEATURES)
113             if (!rmclientIsAdminByHandle(hClient, privLevel))
114 #else
115             if (privLevel < RS_PRIV_LEVEL_KERNEL)
116 #endif
117             {
118                 return NV_ERR_INSUFFICIENT_PERMISSIONS;
119             }
120         }
121     }
122 
123     //
124     // If NVOS32_TYPE indicates ISO requirements, set
125     // NVOS32_ATTR2_NISO_DISPLAY_YES so it can be used within RM instead of
126     // NVOS32_TYPE for ISO determination.
127     //
128     if (bIso)
129     {
130         pAllocData->attr2 = FLD_SET_DRF(OS32, _ATTR2, _ISO, _YES,
131                                         pAllocData->attr2);
132     }
133 
134     if (!(pAllocData->flags & NVOS32_ALLOC_FLAGS_USE_BEGIN_END))
135     {
136         NV_ASSERT_OR_RETURN((pAllocData->rangeLo == 0) &&
137                         (pAllocData->rangeHi == 0), NV_ERR_INVALID_ARGUMENT);
138     }
139     NV_PRINTF(LEVEL_INFO, "MMU_PROFILER Attr 0x%x Type 0x%x Attr2 0x%x\n",
140               pAllocData->attr, pAllocData->type, pAllocData->attr2);
141 
142     // Make sure that encryption is supported if it is requested
143     if ((pAllocData->flags & NVOS32_ALLOC_FLAGS_TURBO_CIPHER_ENCRYPTED) &&
144         DRF_VAL(OS32, _ATTR, _LOCATION, pAllocData->attr) == NVOS32_ATTR_LOCATION_VIDMEM)
145     {
146         NV_PRINTF(LEVEL_ERROR,
147                   "Encryption requested for video memory on a non-0FB chip;\n");
148         return NV_ERR_INVALID_ARGUMENT;
149     }
150 
151     if (FLD_TEST_DRF(OS32, _ATTR2, _ALLOCATE_FROM_SUBHEAP, _YES, pAllocData->attr2))
152     {
153         NV_CHECK_OR_RETURN(LEVEL_ERROR, FLD_TEST_DRF(OS32, _ATTR, _LOCATION, _VIDMEM, pAllocData->attr),
154                            NV_ERR_INVALID_ARGUMENT);
155         return NV_ERR_INVALID_ARGUMENT;
156     }
157 
158     return NV_OK;
159 }
160 
stdmemDumpInputAllocParams(NV_MEMORY_ALLOCATION_PARAMS * pAllocData,CALL_CONTEXT * pCallContext)161 void stdmemDumpInputAllocParams
162 (
163     NV_MEMORY_ALLOCATION_PARAMS  *pAllocData,
164     CALL_CONTEXT                 *pCallContext
165 )
166 {
167     NV_PRINTF(LEVEL_INFO, "stdmemConstruct input\n");
168     NV_PRINTF(LEVEL_INFO, "          Owner: 0x%x\n", pAllocData->owner);
169     NV_PRINTF(LEVEL_INFO, "        hMemory: 0x%x\n", pCallContext->pResourceRef->hResource);
170     NV_PRINTF(LEVEL_INFO, "           Type: 0x%x\n", pAllocData->type);
171     NV_PRINTF(LEVEL_INFO, "          Flags: 0x%x\n", pAllocData->flags);
172     NV_PRINTF(LEVEL_INFO, "          Begin: 0x%08llx\n", pAllocData->rangeLo);
173     NV_PRINTF(LEVEL_INFO, "            End: 0x%08llx\n", pAllocData->rangeHi);
174     NV_PRINTF(LEVEL_INFO, "         Height: 0x%x\n", pAllocData->height);
175     NV_PRINTF(LEVEL_INFO, "          Width: 0x%x\n", pAllocData->width);
176     NV_PRINTF(LEVEL_INFO, "          Pitch: 0x%x\n", pAllocData->pitch);
177     NV_PRINTF(LEVEL_INFO, "           Size: 0x%08llx\n", pAllocData->size);
178     NV_PRINTF(LEVEL_INFO, "      Alignment: 0x%08llx\n", pAllocData->alignment);
179     NV_PRINTF(LEVEL_INFO, "         Offset: 0x%08llx\n", pAllocData->offset);
180     NV_PRINTF(LEVEL_INFO, "           Attr: 0x%x\n", pAllocData->attr);
181     NV_PRINTF(LEVEL_INFO, "          Attr2: 0x%x\n", pAllocData->attr2);
182     NV_PRINTF(LEVEL_INFO, "         Format: 0x%x\n", pAllocData->format);
183     NV_PRINTF(LEVEL_INFO, "      ComprCovg: 0x%x\n", pAllocData->comprCovg);
184     NV_PRINTF(LEVEL_INFO, "      ZCullCovg: 0x%x\n", pAllocData->zcullCovg);
185     NV_PRINTF(LEVEL_INFO, "     CtagOffset: 0x%x\n", pAllocData->ctagOffset);
186     NV_PRINTF(LEVEL_INFO, "       hVASpace: 0x%x\n", pAllocData->hVASpace);
187     NV_PRINTF(LEVEL_INFO, "            tag: 0x%x\n", pAllocData->tag);
188 }
189 
stdmemDumpOutputAllocParams(NV_MEMORY_ALLOCATION_PARAMS * pAllocData)190 void stdmemDumpOutputAllocParams
191 (
192     NV_MEMORY_ALLOCATION_PARAMS  *pAllocData
193 )
194 {
195     NV_PRINTF(LEVEL_INFO, "stdmemConstruct output\n");
196     NV_PRINTF(LEVEL_INFO, "         Height: 0x%x\n", pAllocData->height);
197     NV_PRINTF(LEVEL_INFO, "          Width: 0x%x\n", pAllocData->width);
198     NV_PRINTF(LEVEL_INFO, "          Pitch: 0x%x\n", pAllocData->pitch);
199     NV_PRINTF(LEVEL_INFO, "           Size: 0x%08llx\n", pAllocData->size);
200     NV_PRINTF(LEVEL_INFO, "      Alignment: 0x%08llx\n", pAllocData->alignment);
201     NV_PRINTF(LEVEL_INFO, "         Offset: 0x%08llx\n", pAllocData->offset);
202     NV_PRINTF(LEVEL_INFO, "           Attr: 0x%x\n", pAllocData->attr);
203     NV_PRINTF(LEVEL_INFO, "          Attr2: 0x%x\n", pAllocData->attr2);
204     NV_PRINTF(LEVEL_INFO, "         Format: 0x%x\n", pAllocData->format);
205     NV_PRINTF(LEVEL_INFO, "      ComprCovg: 0x%x\n", pAllocData->comprCovg);
206     NV_PRINTF(LEVEL_INFO, "      ZCullCovg: 0x%x\n", pAllocData->zcullCovg);
207 }
208 
209 NV_STATUS
stdmemConstruct_IMPL(StandardMemory * pStandardMemory,CALL_CONTEXT * pCallContext,RS_RES_ALLOC_PARAMS_INTERNAL * pParams)210 stdmemConstruct_IMPL
211 (
212     StandardMemory               *pStandardMemory,
213     CALL_CONTEXT                 *pCallContext,
214     RS_RES_ALLOC_PARAMS_INTERNAL *pParams
215 )
216 {
217     return NV_OK;
218 }
219 
220 
stdmemCanCopy_IMPL(StandardMemory * pStandardMemory)221 NvBool stdmemCanCopy_IMPL(StandardMemory *pStandardMemory)
222 {
223     return NV_TRUE;
224 }
225 
226 /*!
227  * stdmemQueryPageSize
228  *
229  * @brief
230  *     Returns page size requested by client.
231  *
232  * @param[in] pMemoryManager MemoryManager pointer
233  * @param[in] hClient        Client handle.
234  * @param[in] pAllocData     Pointer to VIDHEAP_ALLOC_DATA
235  *
236  * @returns
237  *      The page size in bytes.
238  */
239 NvU64
stdmemQueryPageSize(MemoryManager * pMemoryManager,NvHandle hClient,NV_MEMORY_ALLOCATION_PARAMS * pAllocData)240 stdmemQueryPageSize
241 (
242     MemoryManager               *pMemoryManager,
243     NvHandle                     hClient,
244     NV_MEMORY_ALLOCATION_PARAMS *pAllocData
245 )
246 {
247     NvU32 retAttr  = pAllocData->attr;
248     NvU32 retAttr2 = pAllocData->attr2;
249 
250     return memmgrDeterminePageSize(pMemoryManager, hClient, pAllocData->size,
251                                    pAllocData->format, pAllocData->flags, &retAttr, &retAttr2);
252 }
253 
254 //
255 // Control calls for system memory objects maintained outside the heap.
256 //
257 
stdmemGetSysmemPageSize_IMPL(OBJGPU * pGpu,StandardMemory * pStdMemory)258 NvU64 stdmemGetSysmemPageSize_IMPL(OBJGPU * pGpu, StandardMemory *pStdMemory)
259 {
260     return GPU_GET_MEMORY_MANAGER(pGpu)->sysmemPageSize;
261 }
262