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