1 /* 2 * SPDX-FileCopyrightText: Copyright (c) 2021-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 #include "gpu/falcon/kernel_falcon.h" 24 #include "gpu/nvlink/kernel_nvlink.h" 25 #include "gpu/fifo/kernel_fifo.h" 26 #include "gpu/fifo/kernel_channel.h" 27 #include "gpu/fifo/kernel_channel_group.h" 28 #include "gpu/fifo/kernel_channel_group_api.h" 29 #include "gpu/subdevice/subdevice.h" 30 #include "gpu/mem_mgr/mem_mgr.h" 31 #include "vgpu/rpc.h" 32 #include "ctrl/ctrl2080/ctrl2080flcn.h" 33 34 NV_STATUS subdeviceCtrlCmdFlcnGetCtxBufferInfo_IMPL 35 ( Subdevice *pSubdevice, 36 NV2080_CTRL_FLCN_GET_CTX_BUFFER_INFO_PARAMS *pParams 37 ) 38 { 39 POBJGPU pGpu = GPU_RES_GET_GPU(pSubdevice); 40 PMEMORY_DESCRIPTOR pMemDesc, pRootMemDesc; 41 RsClient *pUserClient; 42 KernelChannel *pKernelChannel = NULL; 43 NV_STATUS status = NV_OK; 44 NvU64 pageSize; 45 NvU8 *pUuid = NULL; 46 47 // 48 // vGPU: 49 // 50 // Since vGPU does all real hardware management in the 51 // host, if we are in guest OS (where IS_VIRTUAL(pGpu) is true), 52 // do an RPC to the host to get context buffers information. 53 // 54 if (IS_VIRTUAL_WITHOUT_SRIOV(pGpu) || 55 (IS_VIRTUAL_WITH_SRIOV(pGpu) && gpuIsWarBug200577889SriovHeavyEnabled(pGpu))) 56 { 57 CALL_CONTEXT *pCallContext = resservGetTlsCallContext(); 58 RmCtrlParams *pRmCtrlParams = pCallContext->pControlParams; 59 60 NV_RM_RPC_CONTROL(pGpu, 61 pRmCtrlParams->hClient, 62 pRmCtrlParams->hObject, 63 pRmCtrlParams->cmd, 64 pRmCtrlParams->pParams, 65 pRmCtrlParams->paramsSize, 66 status); 67 return status; 68 } 69 70 NV_CHECK_OK_OR_RETURN(LEVEL_INFO, 71 serverGetClientUnderLock(&g_resServ, pParams->hUserClient, &pUserClient)); 72 73 NV_CHECK_OK_OR_RETURN(LEVEL_INFO, 74 CliGetKernelChannel(pUserClient, pParams->hChannel, &pKernelChannel)); 75 NV_ASSERT_OR_RETURN(pKernelChannel != NULL, NV_ERR_INVALID_CHANNEL); 76 77 switch (kchannelGetEngineType(pKernelChannel)) 78 { 79 case RM_ENGINE_TYPE_SEC2: 80 { 81 break; 82 } 83 default: 84 { 85 return NV_ERR_NOT_SUPPORTED; 86 } 87 } 88 89 NV_ASSERT_OK_OR_RETURN(kchangrpGetEngineContextMemDesc(pGpu, pKernelChannel->pKernelChannelGroupApi->pKernelChannelGroup, &pMemDesc)); 90 pRootMemDesc = memdescGetRootMemDesc(pMemDesc, NULL); 91 92 pParams->bufferHandle = NV_PTR_TO_NvP64(pMemDesc); 93 pParams->bIsContigous = memdescGetContiguity(pMemDesc, AT_GPU); 94 pParams->aperture = memdescGetAddressSpace(pMemDesc); 95 pParams->pageCount = pMemDesc->PageCount; 96 pParams->kind = memdescGetPteKindForGpu(pMemDesc, pMemDesc->pGpu); 97 98 { 99 NvU64 physAddr; 100 GMMU_APERTURE aperture = kgmmuGetExternalAllocAperture(pParams->aperture); 101 102 memdescGetPhysAddrsForGpu(pMemDesc, pMemDesc->pGpu, 103 AT_GPU, 0, 0, 1, 104 &physAddr); 105 106 pParams->physAddr = 107 kgmmuEncodePhysAddr(GPU_GET_KERNEL_GMMU(pMemDesc->pGpu), aperture, physAddr, NVLINK_INVALID_FABRIC_ADDR); 108 } 109 110 pageSize = memdescGetPageSize(pMemDesc, AT_GPU); 111 if (pageSize == 0) 112 { 113 status = memmgrSetMemDescPageSize_HAL(pMemDesc->pGpu, 114 GPU_GET_MEMORY_MANAGER(pMemDesc->pGpu), 115 pMemDesc, 116 AT_GPU, 117 RM_ATTR_PAGE_SIZE_DEFAULT); 118 if (status != NV_OK) 119 return status; 120 121 pageSize = memdescGetPageSize(pMemDesc, AT_GPU); 122 NV_ASSERT(pageSize != 0); 123 } 124 125 // 126 // Alignment is used to adjust the mapping VA. Hence, we need to make sure 127 // that it is at least pageSize to make mapping calculation work correctly. 128 // 129 pParams->alignment = (pMemDesc->Alignment != 0) ? 130 NV_ALIGN_UP(pMemDesc->Alignment, pageSize) : pageSize; 131 132 pParams->size = pMemDesc->ActualSize; 133 134 NV_ASSERT_OR_RETURN(pageSize <= NV_U32_MAX, NV_ERR_INVALID_STATE); 135 pParams->pageSize = (NvU32)pageSize; 136 137 pParams->bDeviceDescendant = pRootMemDesc->pGpu != NULL; 138 139 if (pParams->bDeviceDescendant) 140 { 141 NvU32 flags = DRF_DEF(2080_GPU_CMD, _GPU_GET_GID_FLAGS, _TYPE, _SHA1) | 142 DRF_DEF(2080_GPU_CMD, _GPU_GET_GID_FLAGS, _FORMAT, _BINARY); 143 NvU32 uuidLength; 144 // allocates memory for pUuid on success 145 NV_ASSERT_OK_OR_RETURN(gpuGetGidInfo(pGpu, &pUuid, &uuidLength, flags)); 146 if (uuidLength == sizeof(pParams->uuid)) 147 portMemCopy(pParams->uuid, uuidLength, pUuid, uuidLength); 148 else 149 { 150 status = NV_ERR_INVALID_ARGUMENT; 151 goto done; 152 } 153 } 154 155 done: 156 portMemFree(pUuid); 157 return status; 158 } 159 160 NV_STATUS 161 subdeviceCtrlCmdFlcnGetCtxBufferSize_IMPL 162 ( 163 Subdevice *pSubdevice, 164 NV2080_CTRL_FLCN_GET_CTX_BUFFER_SIZE_PARAMS *pParams 165 ) 166 { 167 POBJGPU pGpu = GPU_RES_GET_GPU(pSubdevice); 168 PMEMORY_DESCRIPTOR pMemDesc; 169 KernelChannel *pKernelChannel = NULL; 170 NV_STATUS status = NV_OK; 171 NvU64 alignment; 172 NvU64 pageSize; 173 NvU64 totalBufferSize; 174 175 // 176 // vGPU: 177 // 178 // Since vGPU does all real hardware management in the 179 // host, if we are in guest OS (where IS_VIRTUAL(pGpu) is true), 180 // do an RPC to the host to fetch the engine context buffer size. 181 // 182 if (IS_VIRTUAL_WITHOUT_SRIOV(pGpu) || 183 (IS_VIRTUAL_WITH_SRIOV(pGpu) && gpuIsWarBug200577889SriovHeavyEnabled(pGpu))) 184 { 185 CALL_CONTEXT *pCallContext = resservGetTlsCallContext(); 186 RmCtrlParams *pRmCtrlParams = pCallContext->pControlParams; 187 188 NV_RM_RPC_CONTROL(pGpu, 189 pRmCtrlParams->hClient, 190 pRmCtrlParams->hObject, 191 pRmCtrlParams->cmd, 192 pRmCtrlParams->pParams, 193 pRmCtrlParams->paramsSize, 194 status); 195 return status; 196 } 197 198 NV_CHECK_OK_OR_RETURN(LEVEL_INFO, 199 CliGetKernelChannel(RES_GET_CLIENT(pSubdevice), pParams->hChannel, 200 &pKernelChannel)); 201 NV_ASSERT_OR_RETURN(pKernelChannel != NULL, NV_ERR_INVALID_CHANNEL); 202 203 switch (kchannelGetEngineType(pKernelChannel)) 204 { 205 case RM_ENGINE_TYPE_SEC2: 206 { 207 break; 208 } 209 default: 210 { 211 return NV_ERR_NOT_SUPPORTED; 212 } 213 } 214 215 NV_ASSERT_OK_OR_RETURN(kchangrpGetEngineContextMemDesc(pGpu, pKernelChannel->pKernelChannelGroupApi->pKernelChannelGroup, &pMemDesc)); 216 217 pageSize = memdescGetPageSize(pMemDesc, AT_GPU); 218 if (pageSize == 0) 219 { 220 status = memmgrSetMemDescPageSize_HAL(pMemDesc->pGpu, 221 GPU_GET_MEMORY_MANAGER(pMemDesc->pGpu), 222 pMemDesc, 223 AT_GPU, 224 RM_ATTR_PAGE_SIZE_DEFAULT); 225 if (status != NV_OK) 226 return status; 227 228 pageSize = memdescGetPageSize(pMemDesc, AT_GPU); 229 NV_ASSERT(pageSize != 0); 230 } 231 232 // 233 // Adjust the total size by adding the alignment so that the mapping VA can 234 // be adjusted. 235 // 236 alignment = (pMemDesc->Alignment != 0) ? NV_ALIGN_UP(pMemDesc->Alignment, pageSize) : pageSize; 237 totalBufferSize = 0; 238 totalBufferSize += alignment; 239 totalBufferSize += (alignment != 0) ? NV_ALIGN_UP(pMemDesc->ActualSize, alignment) : pMemDesc->ActualSize; 240 pParams->totalBufferSize = totalBufferSize; 241 242 return status; 243 } 244