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