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