1 /*
2  * SPDX-FileCopyrightText: Copyright (c) 2020-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 #define NVOC_KERNEL_GRAPHICS_H_PRIVATE_ACCESS_ALLOWED
25 
26 
27 #include "rmconfig.h"
28 
29 #include "kernel/gpu/gr/kernel_graphics_manager.h"
30 #include "kernel/gpu/gr/kernel_graphics.h"
31 #include "kernel/gpu/mig_mgr/kernel_mig_manager.h"
32 #include "kernel/gpu/device/device.h"
33 #include "kernel/gpu/subdevice/subdevice.h"
34 #include "kernel/rmapi/rmapi_utils.h"
35 #include "kernel/core/locks.h"
36 #include "kernel/gpu/mem_sys/kern_mem_sys.h"
37 #include "kernel/mem_mgr/gpu_vaspace.h"
38 #include "virtualization/hypervisor/hypervisor.h"
39 #include "nvRmReg.h"
40 #include "kernel/gpu/mem_mgr/mem_mgr.h"
41 #include "kernel/gpu/mem_mgr/heap.h"
42 #include "kernel/gpu/intr/engine_idx.h"
43 #include "gpu/mem_mgr/virt_mem_allocator.h"
44 #include "gpu/mmu/kern_gmmu.h"
45 #include "platform/sli/sli.h"
46 #include "rmapi/rs_utils.h"
47 #include "rmapi/client.h"
48 
49 #include "vgpu/vgpu_events.h"
50 #include "vgpu/rpc.h"
51 
52 #include "class/clb0c0.h"
53 #include "class/clb1c0.h"
54 #include "class/clc0c0.h"
55 #include "class/clc1c0.h"
56 #include "class/clc3c0.h"
57 #include "class/clc5c0.h"
58 #include "class/clc6c0.h"
59 #include "class/clc7c0.h"
60 #include "class/clcbc0.h"
61 
62 #include "class/cl0080.h"
63 #include "class/cl2080.h"
64 #include "class/cla06f.h"
65 #include "class/cla06fsubch.h"
66 #include "class/cl90f1.h" // FERMI_VASPACE_A
67 #include "class/cl003e.h" // NV01_MEMORY_SYSTEM
68 #include "class/cl50a0.h" // NV50_MEMORY_VIRTUAL
69 #include "class/cl0040.h" // NV01_MEMORY_LOCAL_USER
70 #include "class/clc36f.h" // VOLTA_CHANNEL_GPFIFO_A
71 #include "class/clc46f.h" // TURING_CHANNEL_GPFIFO_A
72 #include "class/clc56f.h" // AMPERE_CHANNEL_GPFIFO_A
73 #include "class/clc86f.h" // HOPPER_CHANNEL_GPFIFO_A
74 #include "class/clc637.h"
75 #include "class/clc638.h"
76 
77 //
78 // We use NV2080_CTRL_INTERNAL_GR_MAX_GPC to statically allocate certain
79 // GPC related array in ctrl call header file. We will need to adjust
80 // NV2080_CTRL_INTERNAL_GR_MAX_GPC if some day KGRMGR_MAX_GPC gets changed
81 //
82 ct_assert(NV2080_CTRL_INTERNAL_GR_MAX_GPC == KGRMGR_MAX_GPC);
83 
84 //
85 // Ensure the external and internal ENGINE_CONTEXT_PROPERTIES_ENGINE_ID_COUNT
86 // will always in sync
87 //
88 ct_assert(NV2080_CTRL_INTERNAL_ENGINE_CONTEXT_PROPERTIES_ENGINE_ID_COUNT ==
89           NV0080_CTRL_FIFO_GET_ENGINE_CONTEXT_PROPERTIES_ENGINE_ID_COUNT);
90 
91 typedef struct KGRAPHICS_PRIVATE_DATA
92 {
93     NvBool bInitialized;
94     KGRAPHICS_STATIC_INFO staticInfo;
95 } KGRAPHICS_PRIVATE_DATA;
96 static NV_STATUS _kgraphicsMapGlobalCtxBuffer(OBJGPU *pGpu, KernelGraphics *pKernelGraphics, NvU32 gfid, OBJVASPACE *,
97                                        KernelGraphicsContext *, GR_GLOBALCTX_BUFFER, NvBool bIsReadOnly);
98 static NV_STATUS _kgraphicsPostSchedulingEnableHandler(OBJGPU *, void *);
99 
100 static void
_kgraphicsInitRegistryOverrides(OBJGPU * pGpu,KernelGraphics * pKernelGraphics)101 _kgraphicsInitRegistryOverrides(OBJGPU *pGpu, KernelGraphics *pKernelGraphics)
102 {
103     {
104         NvU32 data;
105 
106         if (osReadRegistryDword(pGpu, NV_REG_STR_RM_FORCE_GR_SCRUBBER_CHANNEL, &data) == NV_OK)
107         {
108             if (data == NV_REG_STR_RM_FORCE_GR_SCRUBBER_CHANNEL_DISABLE)
109             {
110                 kgraphicsSetBug4208224WAREnabled(pGpu, pKernelGraphics, NV_FALSE);
111             }
112             else if (data == NV_REG_STR_RM_FORCE_GR_SCRUBBER_CHANNEL_ENABLE)
113             {
114                 kgraphicsSetBug4208224WAREnabled(pGpu, pKernelGraphics, NV_TRUE);
115             }
116         }
117     }
118     return;
119 }
120 
121 NV_STATUS
kgraphicsConstructEngine_IMPL(OBJGPU * pGpu,KernelGraphics * pKernelGraphics,ENGDESCRIPTOR engDesc)122 kgraphicsConstructEngine_IMPL
123 (
124     OBJGPU         *pGpu,
125     KernelGraphics *pKernelGraphics,
126     ENGDESCRIPTOR   engDesc
127 )
128 {
129     KGRAPHICS_PRIVATE_DATA *pPrivate;
130     NvU32 idx;
131     GR_GLOBALCTX_BUFFER buf;
132     GR_CTX_BUFFER localBuf;
133 
134     pKernelGraphics->instance = ENGDESC_FIELD(engDesc, _INST);
135 
136     pPrivate = portMemAllocNonPaged(sizeof(*pPrivate));
137     if (pPrivate == NULL)
138         return NV_ERR_NO_MEMORY;
139     portMemSet(pPrivate, 0, sizeof(*pPrivate));
140     pKernelGraphics->pPrivate = pPrivate;
141 
142     // All local ctx buffers default to uncached FB preferred
143     FOR_EACH_IN_ENUM(GR_CTX_BUFFER, localBuf)
144     {
145         pKernelGraphics->ctxAttr[localBuf].pAllocList = ADDRLIST_FBMEM_PREFERRED;
146         pKernelGraphics->ctxAttr[localBuf].cpuAttr = NV_MEMORY_UNCACHED;
147     }
148     FOR_EACH_IN_ENUM_END;
149 
150     // Process instloc overrides
151     {
152         struct
153         {
154             GR_CTX_BUFFER buf;
155             NvU32 override;
156         } instlocOverrides[] =
157         {
158             { GR_CTX_BUFFER_MAIN,      DRF_VAL(_REG_STR_RM, _INST_LOC,   _GRCTX, pGpu->instLocOverrides) },
159             { GR_CTX_BUFFER_PATCH,     DRF_VAL(_REG_STR_RM, _INST_LOC_2, _CTX_PATCH, pGpu->instLocOverrides2) },
160             { GR_CTX_BUFFER_ZCULL,     DRF_VAL(_REG_STR_RM, _INST_LOC_2, _ZCULLCTX, pGpu->instLocOverrides2) },
161             { GR_CTX_BUFFER_PM,        DRF_VAL(_REG_STR_RM, _INST_LOC_2, _PMCTX, pGpu->instLocOverrides2) },
162             { GR_CTX_BUFFER_PREEMPT,   DRF_VAL(_REG_STR_RM, _INST_LOC_3, _PREEMPT_BUFFER, pGpu->instLocOverrides3) },
163             { GR_CTX_BUFFER_BETA_CB,   DRF_VAL(_REG_STR_RM, _INST_LOC_3, _GFXP_BETACB_BUFFER, pGpu->instLocOverrides3) },
164             { GR_CTX_BUFFER_PAGEPOOL,  DRF_VAL(_REG_STR_RM, _INST_LOC_3, _GFXP_PAGEPOOL_BUFFER, pGpu->instLocOverrides3) },
165             { GR_CTX_BUFFER_SPILL,     DRF_VAL(_REG_STR_RM, _INST_LOC_3, _GFXP_SPILL_BUFFER, pGpu->instLocOverrides3) },
166             { GR_CTX_BUFFER_RTV_CB,    DRF_VAL(_REG_STR_RM, _INST_LOC_3, _GFXP_RTVCB_BUFFER, pGpu->instLocOverrides3) },
167             { GR_CTX_BUFFER_SETUP,     DRF_VAL(_REG_STR_RM, _INST_LOC_4, _GFXP_SETUP_BUFFER, pGpu->instLocOverrides4) }
168         };
169 
170         for (idx = 0; idx < NV_ARRAY_ELEMENTS(instlocOverrides); ++idx)
171         {
172             memdescOverrideInstLocList(instlocOverrides[idx].override,
173                                        NV_ENUM_TO_STRING(GR_CTX_BUFFER, instlocOverrides[idx].buf),
174                                        &pKernelGraphics->ctxAttr[instlocOverrides[idx].buf].pAllocList,
175                                        &pKernelGraphics->ctxAttr[instlocOverrides[idx].buf].cpuAttr);
176         }
177     }
178 
179     // Most global ctx buffers default to uncached FB preferred
180     FOR_EACH_IN_ENUM(GR_GLOBALCTX_BUFFER, buf)
181     {
182         pKernelGraphics->globalCtxBuffersInfo.globalCtxAttr[buf].pAllocList = ADDRLIST_FBMEM_PREFERRED;
183         pKernelGraphics->globalCtxBuffersInfo.globalCtxAttr[buf].cpuAttr = NV_MEMORY_UNCACHED;
184     }
185     FOR_EACH_IN_ENUM_END;
186 
187     // FECS event buffer defaults to cached SYSMEM
188     pKernelGraphics->globalCtxBuffersInfo.globalCtxAttr[GR_GLOBALCTX_BUFFER_FECS_EVENT].pAllocList = ADDRLIST_SYSMEM_ONLY;
189     pKernelGraphics->globalCtxBuffersInfo.globalCtxAttr[GR_GLOBALCTX_BUFFER_FECS_EVENT].cpuAttr    = NV_MEMORY_CACHED;
190 
191     // Process instloc overrides
192     {
193         struct
194         {
195             GR_GLOBALCTX_BUFFER buf;
196             NvU32 override;
197         } instlocOverrides[] =
198         {
199             { GR_GLOBALCTX_BUFFER_FECS_EVENT,                   DRF_VAL(_REG_STR_RM, _INST_LOC_4, _FECS_EVENT_BUF, pGpu->instLocOverrides4) },
200             { GR_GLOBALCTX_BUFFER_ATTRIBUTE_CB,                 DRF_VAL(_REG_STR_RM, _INST_LOC_2, _ATTR_CB, pGpu->instLocOverrides2) },
201             { GR_GLOBALCTX_BUFFER_BUNDLE_CB,                    DRF_VAL(_REG_STR_RM, _INST_LOC_2, _BUNDLE_CB, pGpu->instLocOverrides2) },
202             { GR_GLOBALCTX_BUFFER_PAGEPOOL,                     DRF_VAL(_REG_STR_RM, _INST_LOC_2, _PAGEPOOL, pGpu->instLocOverrides2) },
203             { GR_GLOBALCTX_BUFFER_PRIV_ACCESS_MAP,              DRF_VAL(_REG_STR_RM, _INST_LOC_3, _PRIV_ACCESS_MAP, pGpu->instLocOverrides3) },
204             { GR_GLOBALCTX_BUFFER_UNRESTRICTED_PRIV_ACCESS_MAP, DRF_VAL(_REG_STR_RM, _INST_LOC_3, _PRIV_ACCESS_MAP, pGpu->instLocOverrides3) },
205             { GR_GLOBAL_BUFFER_GLOBAL_PRIV_ACCESS_MAP,          DRF_VAL(_REG_STR_RM, _INST_LOC_3, _PRIV_ACCESS_MAP, pGpu->instLocOverrides3) },
206             { GR_GLOBALCTX_BUFFER_RTV_CB,                       DRF_VAL(_REG_STR_RM, _INST_LOC_3, _RTVCB_BUFFER, pGpu->instLocOverrides3) }
207         };
208 
209         for (idx = 0; idx < NV_ARRAY_ELEMENTS(instlocOverrides); ++idx)
210         {
211             memdescOverrideInstLocList(instlocOverrides[idx].override,
212                                        NV_ENUM_TO_STRING(GR_GLOBALCTX_BUFFER, instlocOverrides[idx].buf),
213                                        &pKernelGraphics->globalCtxBuffersInfo.globalCtxAttr[instlocOverrides[idx].buf].pAllocList,
214                                        &pKernelGraphics->globalCtxBuffersInfo.globalCtxAttr[instlocOverrides[idx].buf].cpuAttr);
215         }
216     }
217 
218     // Copy final global buffer attributes for local versions
219     FOR_EACH_IN_ENUM(GR_GLOBALCTX_BUFFER, buf)
220     {
221         // Host RM cannot allocate system memory on behalf of the VF RM, so force FB.
222         pKernelGraphics->globalCtxBuffersInfo.vfGlobalCtxAttr[buf].pAllocList = ADDRLIST_FBMEM_ONLY;
223         pKernelGraphics->globalCtxBuffersInfo.vfGlobalCtxAttr[buf].cpuAttr = NV_MEMORY_UNCACHED;
224 
225         // Local context allocation
226         pKernelGraphics->globalCtxBuffersInfo.localCtxAttr[buf] = pKernelGraphics->globalCtxBuffersInfo.globalCtxAttr[buf];
227     }
228     FOR_EACH_IN_ENUM_END;
229 
230     //
231     // Default context buffers to non size aligned. The attribute buffer is
232     // required to be mapped with an offset naturally aligned to the size.
233     //
234     for (idx = 0; idx < GR_GLOBALCTX_BUFFER_COUNT; idx++)
235         pKernelGraphics->globalCtxBuffersInfo.bSizeAligned[idx] = NV_FALSE;
236     pKernelGraphics->globalCtxBuffersInfo.bSizeAligned[GR_GLOBALCTX_BUFFER_ATTRIBUTE_CB] = NV_TRUE;
237 
238     NV_ASSERT_OK_OR_RETURN(fecsCtxswLoggingInit(pGpu, pKernelGraphics, &pKernelGraphics->pFecsTraceInfo));
239 
240     _kgraphicsInitRegistryOverrides(pGpu, pKernelGraphics);
241     return NV_OK;
242 }
243 
244 void
kgraphicsDestruct_IMPL(KernelGraphics * pKernelGraphics)245 kgraphicsDestruct_IMPL
246 (
247     KernelGraphics *pKernelGraphics
248 )
249 {
250     OBJGPU *pGpu = ENG_GET_GPU(pKernelGraphics);
251 
252     fecsCtxswLoggingTeardown(pGpu, pKernelGraphics);
253     pKernelGraphics->pFecsTraceInfo = NULL;
254     kgraphicsInvalidateStaticInfo(pGpu, pKernelGraphics);
255 
256     portMemFree(pKernelGraphics->pPrivate);
257     pKernelGraphics->pPrivate = NULL;
258 }
259 
260 NV_STATUS
kgraphicsStateInitLocked_IMPL(OBJGPU * pGpu,KernelGraphics * pKernelGraphics)261 kgraphicsStateInitLocked_IMPL
262 (
263     OBJGPU *pGpu,
264     KernelGraphics *pKernelGraphics
265 )
266 {
267     NvU32 nGlobalCtx = 1;
268     NvU32 numClasses;
269 
270     NV_ASSERT_OK_OR_RETURN(gpuGetClassList(pGpu, &numClasses, NULL, ENG_GR(pKernelGraphics->instance)));
271 
272     //
273     // Number of supported class can be zero when Graphics engine is disabled, but we still
274     // need those classes in ClassDB for KernelGraphics engine operation, thus here we are adding
275     // the ENG_GR(X) supported classes back to ClassDB
276     //
277     if (numClasses == 0)
278     {
279         PGPU_ENGINE_ORDER pEngineOrder = &pGpu->engineOrder;
280         const CLASSDESCRIPTOR *pClassDesc = &pEngineOrder->pClassDescriptors[0];
281         NvU32 i;
282         NvU32 classNum;
283 
284         for (i = 0; i < pEngineOrder->numClassDescriptors; i++)
285         {
286             classNum = pClassDesc[i].externalClassId;
287             if (classNum == (NvU32)~0)
288                 continue;
289 
290             if (ENG_GR(pKernelGraphics->instance) == pClassDesc[i].engDesc)
291             {
292                 NV_PRINTF(LEVEL_INFO, "Adding class ID 0x%x to ClassDB\n", classNum);
293                 NV_ASSERT_OK_OR_RETURN(
294                     gpuAddClassToClassDBByEngTagClassId(pGpu, ENG_GR(pKernelGraphics->instance), classNum));
295             }
296         }
297     }
298 
299     //
300     // Allocate guest context db array
301     //
302     if (gpuIsSriovEnabled(pGpu))
303     {
304         nGlobalCtx = VMMU_MAX_GFID;
305     }
306 
307     pKernelGraphics->globalCtxBuffersInfo.pGlobalCtxBuffers = portMemAllocNonPaged(sizeof(*pKernelGraphics->globalCtxBuffersInfo.pGlobalCtxBuffers) * nGlobalCtx);
308     if (pKernelGraphics->globalCtxBuffersInfo.pGlobalCtxBuffers == NULL)
309     {
310         return NV_ERR_NO_MEMORY;
311     }
312     portMemSet(pKernelGraphics->globalCtxBuffersInfo.pGlobalCtxBuffers, 0,
313             sizeof(*pKernelGraphics->globalCtxBuffersInfo.pGlobalCtxBuffers) * nGlobalCtx);
314 
315     if (pKernelGraphics->instance == 0)
316     {
317         //
318         // GSP_CLIENT creates the golden context channel GR post load. However,
319         // if PMA scrubber is enabled, a scrubber channel must be constructed
320         // first as a part of Fifo post load. Hence, add the golden channel
321         // creation as a fifo post-scheduling-enablement callback.
322         //
323         NV_ASSERT_OK_OR_RETURN(
324             kfifoAddSchedulingHandler(pGpu, GPU_GET_KERNEL_FIFO(pGpu),
325                                       _kgraphicsPostSchedulingEnableHandler,
326                                       (void *)((NvUPtr)(pKernelGraphics->instance)),
327                                       NULL, NULL));
328     }
329 
330     pKernelGraphics->bug4208224Info.hClient      = NV01_NULL_OBJECT;
331     pKernelGraphics->bug4208224Info.hDeviceId    = NV01_NULL_OBJECT;
332     pKernelGraphics->bug4208224Info.hSubdeviceId = NV01_NULL_OBJECT;
333     pKernelGraphics->bug4208224Info.bConstructed = NV_FALSE;
334     return NV_OK;
335 }
336 
337 NV_STATUS
kgraphicsStateUnload_IMPL(OBJGPU * pGpu,KernelGraphics * pKernelGraphics,NvU32 flags)338 kgraphicsStateUnload_IMPL
339 (
340     OBJGPU *pGpu,
341     KernelGraphics *pKernelGraphics,
342     NvU32 flags
343 
344 )
345 {
346     if (pKernelGraphics->instance != 0)
347         return NV_OK;
348 
349     kfifoRemoveSchedulingHandler(pGpu, GPU_GET_KERNEL_FIFO(pGpu),
350                                  _kgraphicsPostSchedulingEnableHandler,
351                                  (void *)((NvUPtr)(pKernelGraphics->instance)),
352                                  NULL, NULL);
353 
354     return NV_OK;
355 }
356 
357 NV_STATUS
kgraphicsStateLoad_IMPL(OBJGPU * pGpu,KernelGraphics * pKernelGraphics,NvU32 flags)358 kgraphicsStateLoad_IMPL
359 (
360     OBJGPU *pGpu,
361     KernelGraphics *pKernelGraphics,
362     NvU32 flags
363 )
364 {
365     KernelGraphicsManager *pKernelGraphicsManager = GPU_GET_KERNEL_GRAPHICS_MANAGER(pGpu);
366 
367     if (fecsGetCtxswLogConsumerCount(pGpu, pKernelGraphicsManager) > 0)
368     {
369         fecsBufferMap(pGpu, pKernelGraphics);
370         fecsBufferReset(pGpu, pKernelGraphics);
371     }
372 
373     return NV_OK;
374 }
375 
376 NV_STATUS
kgraphicsStatePreUnload_IMPL(OBJGPU * pGpu,KernelGraphics * pKernelGraphics,NvU32 flags)377 kgraphicsStatePreUnload_IMPL
378 (
379     OBJGPU *pGpu,
380     KernelGraphics *pKernelGraphics,
381     NvU32 flags
382 )
383 {
384     if (pKernelGraphics->bug4208224Info.bConstructed)
385     {
386         RM_API *pRmApi = rmapiGetInterface(RMAPI_GPU_LOCK_INTERNAL);
387         NV2080_CTRL_INTERNAL_KGR_INIT_BUG4208224_WAR_PARAMS params = {0};
388 
389         params.bTeardown = NV_TRUE;
390         NV_ASSERT_OK(pRmApi->Control(pRmApi,
391                      pKernelGraphics->bug4208224Info.hClient,
392                      pKernelGraphics->bug4208224Info.hSubdeviceId,
393                      NV2080_CTRL_CMD_INTERNAL_KGR_INIT_BUG4208224_WAR,
394                      &params,
395                      sizeof(params)));
396         NV_ASSERT_OK(pRmApi->Free(pRmApi, pKernelGraphics->bug4208224Info.hClient, pKernelGraphics->bug4208224Info.hClient));
397         pKernelGraphics->bug4208224Info.bConstructed = NV_FALSE;
398     }
399 
400     fecsBufferUnmap(pGpu, pKernelGraphics);
401 
402     // Release global buffers used as part of the gr context, when not in S/R
403     if (!(flags & GPU_STATE_FLAGS_PRESERVING))
404         kgraphicsFreeGlobalCtxBuffers(pGpu, pKernelGraphics, GPU_GFID_PF);
405 
406     return NV_OK;
407 }
408 
409 void
kgraphicsStateDestroy_IMPL(OBJGPU * pGpu,KernelGraphics * pKernelGraphics)410 kgraphicsStateDestroy_IMPL
411 (
412     OBJGPU *pGpu,
413     KernelGraphics *pKernelGraphics
414 )
415 {
416     fecsBufferTeardown(pGpu, pKernelGraphics);
417 
418     portMemFree(pKernelGraphics->globalCtxBuffersInfo.pGlobalCtxBuffers);
419     pKernelGraphics->globalCtxBuffersInfo.pGlobalCtxBuffers = NULL;
420 }
421 
kgraphicsIsPresent_IMPL(OBJGPU * pGpu,KernelGraphics * pKernelGraphics)422 NvBool kgraphicsIsPresent_IMPL
423 (
424     OBJGPU         *pGpu,
425     KernelGraphics *pKernelGraphics
426 )
427 {
428     KernelFifo *pKernelFifo = GPU_GET_KERNEL_FIFO(pGpu);
429     NvU32 unused;
430 
431     if (IsDFPGA(pGpu))
432         return NV_FALSE;
433 
434     if (IS_MODS_AMODEL(pGpu))
435         return NV_TRUE;
436 
437     return kfifoEngineInfoXlate_HAL(pGpu, pKernelFifo,
438                                     ENGINE_INFO_TYPE_RM_ENGINE_TYPE, (NvU32)RM_ENGINE_TYPE_GR(pKernelGraphics->instance),
439                                     ENGINE_INFO_TYPE_INVALID, &unused) == NV_OK;
440 }
441 
442 NV_STATUS
kgraphicsStatePostLoad_IMPL(OBJGPU * pGpu,KernelGraphics * pKernelGraphics,NvU32 flags)443 kgraphicsStatePostLoad_IMPL
444 (
445     OBJGPU *pGpu,
446     KernelGraphics *pKernelGraphics,
447     NvU32 flags
448 )
449 {
450     const KGRAPHICS_STATIC_INFO *pKernelGraphicsStaticInfo;
451     NV_CHECK_OK_OR_RETURN(LEVEL_ERROR, kgraphicsLoadStaticInfo(pGpu, pKernelGraphics, KMIGMGR_SWIZZID_INVALID));
452     pKernelGraphicsStaticInfo = kgraphicsGetStaticInfo(pGpu, pKernelGraphics);
453 
454     if ((!IS_VIRTUAL(pGpu)) &&
455         (pKernelGraphicsStaticInfo != NULL) &&
456         (pKernelGraphicsStaticInfo->pContextBuffersInfo != NULL) &&
457         (kgraphicsGetGlobalCtxBuffers(pGpu, pKernelGraphics, GPU_GFID_PF)->memDesc[GR_GLOBALCTX_BUFFER_FECS_EVENT] == NULL))
458     {
459         NV_CHECK_OK_OR_RETURN(LEVEL_ERROR,
460             kgraphicsAllocGlobalCtxBuffers_HAL(pGpu, pKernelGraphics, GPU_GFID_PF));
461     }
462 
463     return NV_OK;
464 }
465 
466 /*!
467  * @brief Create a golden image channel after Fifo post load
468  * Instead of lazily waiting until first client request, we proactively create a
469  * golden channel here.
470  */
471 static NV_STATUS
_kgraphicsPostSchedulingEnableHandler(OBJGPU * pGpu,void * pGrIndex)472 _kgraphicsPostSchedulingEnableHandler
473 (
474     OBJGPU *pGpu,
475     void *pGrIndex
476 )
477 {
478     MemoryManager *pMemoryManager = GPU_GET_MEMORY_MANAGER(pGpu);
479     KernelGraphics *pKernelGraphics = GPU_GET_KERNEL_GRAPHICS(pGpu, ((NvU32)(NvUPtr)pGrIndex));
480     const KGRAPHICS_STATIC_INFO *pKernelGraphicsStaticInfo = kgraphicsGetStaticInfo(pGpu, pKernelGraphics);
481 
482     // Nothing to do for non-GSPCLIENT
483     if (!IS_GSP_CLIENT(pGpu) && !kgraphicsIsBug4208224WARNeeded_HAL(pGpu, pKernelGraphics))
484         return NV_OK;
485 
486     // Defer golden context channel creation to GPU instance configuration
487     if (IS_MIG_ENABLED(pGpu))
488         return NV_OK;
489 
490     // Skip for MIG engines with 0 GPCs
491     NV_ASSERT_OR_RETURN(pKernelGraphicsStaticInfo != NULL, NV_ERR_INVALID_STATE);
492     if (pKernelGraphicsStaticInfo->floorsweepingMasks.gpcMask == 0x0)
493         return NV_OK;
494 
495     if (memmgrIsPmaInitialized(pMemoryManager))
496     {
497         Heap *pHeap = GPU_GET_HEAP(pGpu);
498         NvU32 pmaConfig = PMA_QUERY_SCRUB_ENABLED | PMA_QUERY_SCRUB_VALID;
499 
500         NV_ASSERT_OK_OR_RETURN(pmaQueryConfigs(&pHeap->pmaObject, &pmaConfig));
501 
502         //
503         // Scrubber is also constructed from the same Fifo post scheduling
504         // enable callback queue. This check enforces the dependency that
505         // scrubber must be initialized first
506         //
507         if ((pmaConfig & PMA_QUERY_SCRUB_ENABLED) &&
508             !(pmaConfig & PMA_QUERY_SCRUB_VALID))
509         {
510             return NV_WARN_MORE_PROCESSING_REQUIRED;
511         }
512     }
513 
514     NV_CHECK_OK_OR_RETURN(LEVEL_ERROR, kgraphicsCreateGoldenImageChannel(pGpu, pKernelGraphics));
515     if (kgraphicsIsBug4208224WARNeeded_HAL(pGpu, pKernelGraphics))
516     {
517         return kgraphicsInitializeBug4208224WAR_HAL(pGpu, pKernelGraphics);
518     }
519 
520     return NV_OK;
521 }
522 
523 void
kgraphicsInvalidateStaticInfo_IMPL(OBJGPU * pGpu,KernelGraphics * pKernelGraphics)524 kgraphicsInvalidateStaticInfo_IMPL
525 (
526     OBJGPU *pGpu,
527     KernelGraphics *pKernelGraphics
528 )
529 {
530     portMemFree(pKernelGraphics->pPrivate->staticInfo.pGrInfo);
531     pKernelGraphics->pPrivate->staticInfo.pGrInfo = NULL;
532 
533     portMemFree(pKernelGraphics->pPrivate->staticInfo.pPpcMasks);
534     pKernelGraphics->pPrivate->staticInfo.pPpcMasks = NULL;
535 
536     portMemFree(pKernelGraphics->pPrivate->staticInfo.pZcullInfo);
537     pKernelGraphics->pPrivate->staticInfo.pZcullInfo = NULL;
538 
539     portMemFree(pKernelGraphics->pPrivate->staticInfo.pRopInfo);
540     pKernelGraphics->pPrivate->staticInfo.pRopInfo = NULL;
541 
542     portMemFree(pKernelGraphics->pPrivate->staticInfo.pContextBuffersInfo);
543     pKernelGraphics->pPrivate->staticInfo.pContextBuffersInfo = NULL;
544 
545     portMemFree(pKernelGraphics->pPrivate->staticInfo.pSmIssueRateModifier);
546     pKernelGraphics->pPrivate->staticInfo.pSmIssueRateModifier = NULL;
547 
548     portMemFree(pKernelGraphics->pPrivate->staticInfo.pFecsTraceDefines);
549     pKernelGraphics->pPrivate->staticInfo.pFecsTraceDefines = NULL;
550 
551     portMemSet(&pKernelGraphics->pPrivate->staticInfo, 0, sizeof(pKernelGraphics->pPrivate->staticInfo));
552     pKernelGraphics->pPrivate->bInitialized = NV_FALSE;
553 }
554 
555 const KGRAPHICS_STATIC_INFO *
kgraphicsGetStaticInfo_IMPL(OBJGPU * pGpu,KernelGraphics * pKernelGraphics)556 kgraphicsGetStaticInfo_IMPL
557 (
558     OBJGPU *pGpu,
559     KernelGraphics *pKernelGraphics
560 )
561 {
562     KGRAPHICS_PRIVATE_DATA *pPrivate = pKernelGraphics->pPrivate;
563     return ((pPrivate != NULL) && pPrivate->bInitialized) ? &pPrivate->staticInfo : NULL;
564 }
565 
566 static NV_STATUS
_kgraphicsInternalClientAlloc(OBJGPU * pGpu,KernelGraphics * pKernelGraphics,NvU32 swizzId,NvHandle * phClient,NvHandle * phDevice,NvHandle * phSubdevice)567 _kgraphicsInternalClientAlloc
568 (
569     OBJGPU *pGpu,
570     KernelGraphics *pKernelGraphics,
571     NvU32 swizzId,
572     NvHandle *phClient,
573     NvHandle *phDevice,
574     NvHandle *phSubdevice
575 )
576 {
577     RM_API *pRmApi = rmapiGetInterface(RMAPI_GPU_LOCK_INTERNAL); //FIXME = GPU_GET_PHYSICAL_RMAPI(pGpu);
578     NvU32 grIdx = pKernelGraphics->instance;
579 
580     NV_ASSERT_OR_RETURN(phClient != NULL, NV_ERR_INVALID_ARGUMENT);
581     NV_ASSERT_OR_RETURN(phDevice != NULL, NV_ERR_INVALID_ARGUMENT);
582     NV_ASSERT_OR_RETURN(phSubdevice != NULL, NV_ERR_INVALID_ARGUMENT);
583 
584     if (IS_MIG_IN_USE(pGpu))
585     {
586         NvHandle hSubscription;
587 
588         // Delay initialization to GPU instance configuration
589         if (swizzId == KMIGMGR_SWIZZID_INVALID)
590             return NV_ERR_NOT_READY;
591 
592         // With MIG enabled, we need to use a client subscribed to the correct GPU instance.
593         NV_ASSERT_OK_OR_RETURN(
594             rmapiutilAllocClientAndDeviceHandles(pRmApi, pGpu, phClient, phDevice, phSubdevice));
595 
596         {
597             NVC637_ALLOCATION_PARAMETERS params;
598             NV_ASSERT_OK(
599                 serverutilGenResourceHandle(*phClient, &hSubscription));
600             portMemSet(&params, 0, sizeof(params));
601             params.swizzId = swizzId;
602             NV_ASSERT_OK(
603                 pRmApi->AllocWithHandle(pRmApi, *phClient, *phSubdevice, hSubscription, AMPERE_SMC_PARTITION_REF, &params, sizeof(params)));
604         }
605 
606     }
607     else if (grIdx != 0)
608     {
609         // Static data is only defined for GR0 in legacy mode
610         return NV_ERR_NOT_READY;
611     }
612     else
613     {
614         NV_ASSERT_OK_OR_RETURN(
615             rmapiutilAllocClientAndDeviceHandles(pRmApi, pGpu, phClient, phDevice, phSubdevice));
616     }
617 
618     return NV_OK;
619 }
620 
621 /*!
622  * @brief Initialize static data that isn't collected right away
623  */
624 NV_STATUS
kgraphicsInitializeDeferredStaticData_IMPL(OBJGPU * pGpu,KernelGraphics * pKernelGraphics,NvHandle hClient,NvHandle hSubdevice)625 kgraphicsInitializeDeferredStaticData_IMPL
626 (
627     OBJGPU *pGpu,
628     KernelGraphics *pKernelGraphics,
629     NvHandle hClient,
630     NvHandle hSubdevice
631 )
632 {
633     NV2080_CTRL_INTERNAL_STATIC_GR_GET_CONTEXT_BUFFERS_INFO_PARAMS *pParams;
634     KernelMIGManager *pKernelMIGManager = GPU_GET_KERNEL_MIG_MANAGER(pGpu);
635     KGRAPHICS_PRIVATE_DATA *pPrivate = pKernelGraphics->pPrivate;
636     RM_API *pRmApi = rmapiGetInterface(RMAPI_GPU_LOCK_INTERNAL);
637     NvU32 grIdx = pKernelGraphics->instance;
638     NV_STATUS status = NV_OK;
639     NvBool bInternalClientAllocated = NV_FALSE;
640     NvU32 gfid;
641     NvBool bCallingContextPlugin;
642 
643     NV_ASSERT_OK_OR_RETURN(vgpuGetCallingContextGfid(pGpu, &gfid));
644     NV_ASSERT_OK_OR_RETURN(vgpuIsCallingContextPlugin(pGpu, &bCallingContextPlugin));
645 
646     if (bCallingContextPlugin)
647     {
648         gfid = GPU_GFID_PF;
649     }
650 
651     //
652     // Most of GR is stub'd so context related things are not needed in AMODEL.
653     // But this function can be called in some MODS test, so return OK directly
654     // to avoid failing the test.
655     //
656     if (IS_MODS_AMODEL(pGpu))
657         return NV_OK;
658 
659     // Not ready
660     if (!pPrivate->bInitialized)
661         return NV_OK;
662 
663     // Already done
664     if (pPrivate->staticInfo.pContextBuffersInfo != NULL)
665         return NV_OK;
666 
667     // In progress
668     if (pKernelGraphics->bCollectingDeferredStaticData)
669         return NV_OK;
670 
671     if (hClient == NV01_NULL_OBJECT)
672     {
673         NvHandle hDevice = NV01_NULL_OBJECT;
674         NvU32 swizzId = KMIGMGR_SWIZZID_INVALID;
675 
676         if (IS_MIG_IN_USE(pGpu))
677         {
678             MIG_INSTANCE_REF ref;
679 
680             NV_ASSERT_OK_OR_RETURN(
681                 kmigmgrGetMIGReferenceFromEngineType(pGpu, pKernelMIGManager,
682                                                      RM_ENGINE_TYPE_GR(pKernelGraphics->instance), &ref));
683 
684             swizzId = ref.pKernelMIGGpuInstance->swizzId;
685         }
686 
687         status = _kgraphicsInternalClientAlloc(pGpu, pKernelGraphics, swizzId, &hClient, &hDevice, &hSubdevice);
688         if (status == NV_ERR_NOT_READY)
689         {
690             return NV_OK;
691         }
692         NV_ASSERT_OR_RETURN(status == NV_OK, status);
693         NV_ASSERT_OR_RETURN(hClient != NV01_NULL_OBJECT, NV_ERR_INVALID_STATE);
694         bInternalClientAllocated = NV_TRUE;
695     }
696 
697     // Prevent recursion when deferred static data collection is ON
698     pKernelGraphics->bCollectingDeferredStaticData = NV_TRUE;
699 
700     if (IS_MIG_IN_USE(pGpu))
701     {
702         MIG_INSTANCE_REF ref;
703         RM_ENGINE_TYPE localRmEngineType;
704         Subdevice *pSubdevice;
705         RsClient *pClient;
706 
707         NV_CHECK_OK_OR_GOTO(
708             status,
709             LEVEL_ERROR,
710             serverGetClientUnderLock(&g_resServ, hClient, &pClient),
711             cleanup);
712 
713         NV_CHECK_OK_OR_GOTO(
714             status,
715             LEVEL_ERROR,
716             subdeviceGetByHandle(pClient, hSubdevice, &pSubdevice),
717             cleanup);
718 
719         // Physical RM will fill with local indices, so localize the index
720         NV_CHECK_OK_OR_GOTO(
721             status,
722             LEVEL_ERROR,
723             kmigmgrGetInstanceRefFromDevice(pGpu, pKernelMIGManager,
724                                             GPU_RES_GET_DEVICE(pSubdevice),
725                                             &ref),
726             cleanup);
727         NV_CHECK_OK_OR_GOTO(
728             status,
729             LEVEL_ERROR,
730             kmigmgrGetGlobalToLocalEngineType(pGpu, pKernelMIGManager, ref,
731                                               RM_ENGINE_TYPE_GR(grIdx),
732                                               &localRmEngineType),
733             cleanup);
734         grIdx = RM_ENGINE_TYPE_GR_IDX(localRmEngineType);
735     }
736 
737     pParams = portMemAllocNonPaged(sizeof(*pParams));
738     if (pParams == NULL)
739     {
740         return NV_ERR_NO_MEMORY;
741     }
742     portMemSet(pParams, 0, sizeof(*pParams));
743     NV_CHECK_OK_OR_GOTO(
744         status,
745         LEVEL_ERROR,
746         pRmApi->Control(pRmApi,
747                         hClient,
748                         hSubdevice,
749                         NV2080_CTRL_CMD_INTERNAL_STATIC_KGR_GET_CONTEXT_BUFFERS_INFO,
750                         pParams,
751                         sizeof(*pParams)),
752         cleanup_context_buffers_info);
753 
754     pPrivate->staticInfo.pContextBuffersInfo =
755         portMemAllocNonPaged(sizeof(*pPrivate->staticInfo.pContextBuffersInfo));
756 
757     if (pPrivate->staticInfo.pContextBuffersInfo == NULL)
758     {
759         status = NV_ERR_NO_MEMORY;
760         goto cleanup_context_buffers_info;
761     }
762 
763     portMemCopy(pPrivate->staticInfo.pContextBuffersInfo,
764                 sizeof(*pPrivate->staticInfo.pContextBuffersInfo),
765                 &pParams->engineContextBuffersInfo[grIdx],
766                 sizeof(pParams->engineContextBuffersInfo[grIdx]));
767 
768 cleanup_context_buffers_info:
769     portMemFree(pParams);
770 
771     //
772     // We are not cleaning pContextBuffersInfo here since it's used after this
773     // function so has to be cleaned after used.
774     //
775 
776 cleanup:
777     if (bInternalClientAllocated)
778     {
779         pRmApi->Free(pRmApi, hClient, hClient);
780     }
781 
782     pKernelGraphics->bCollectingDeferredStaticData = NV_FALSE;
783 
784     if (status == NV_OK)
785     {
786         //
787         // Allocate Ctx Buffers that are global to all channels if they have yet
788         // to be allocated. We delay them until now to save memory when runs
789         // are done without using graphics contexts!
790         //
791         if (!pKernelGraphics->globalCtxBuffersInfo.pGlobalCtxBuffers[gfid].bAllocated &&
792             (!gpuIsClientRmAllocatedCtxBufferEnabled(pGpu) ||
793              (gpuIsSriovEnabled(pGpu) && IS_GFID_PF(gfid))))
794         {
795             NV_CHECK_OK_OR_RETURN(LEVEL_ERROR,
796                 kgraphicsAllocGrGlobalCtxBuffers_HAL(pGpu, pKernelGraphics, gfid, NULL));
797         }
798     }
799 
800     return status;
801 }
802 
803 NV_STATUS
kgraphicsLoadStaticInfo_VF(OBJGPU * pGpu,KernelGraphics * pKernelGraphics,NvU32 swizzId)804 kgraphicsLoadStaticInfo_VF
805 (
806     OBJGPU *pGpu,
807     KernelGraphics *pKernelGraphics,
808     NvU32 swizzId
809 )
810 {
811     KGRAPHICS_PRIVATE_DATA *pPrivate = pKernelGraphics->pPrivate;
812     VGPU_STATIC_INFO *pVSI = GPU_GET_STATIC_INFO(pGpu);
813     NvU32 grIdx = pKernelGraphics->instance;
814     NVOS_STATUS status = NV_OK;
815 
816     NV_ASSERT_OR_RETURN(pVSI != NULL, NV_ERR_INVALID_STATE);
817     NV_ASSERT_OR_RETURN(pPrivate != NULL, NV_ERR_INVALID_STATE);
818 
819     if (pPrivate->bInitialized)
820         return status;
821 
822     if (IS_MIG_IN_USE(pGpu))
823     {
824         KernelMIGManager *pKernelMIGManager = GPU_GET_KERNEL_MIG_MANAGER(pGpu);
825 
826         //
827         // Delay initialization to GPU instance configuration, unless MODS is using
828         // legacy VGPU mode, in which case the guest never receives a
829         // configuration call
830         //
831         if ((swizzId == KMIGMGR_SWIZZID_INVALID) && !kmigmgrUseLegacyVgpuPolicy(pGpu, pKernelMIGManager))
832             return status;
833 
834         pPrivate->staticInfo.pGrInfo = portMemAllocNonPaged(sizeof(*pPrivate->staticInfo.pGrInfo));
835         if (pPrivate->staticInfo.pGrInfo == NULL)
836         {
837             status = NV_ERR_NO_MEMORY;
838             goto cleanup;
839         }
840 
841         portMemCopy(pPrivate->staticInfo.pGrInfo->infoList,
842                     NV0080_CTRL_GR_INFO_MAX_SIZE * sizeof(*pPrivate->staticInfo.pGrInfo->infoList),
843                     pVSI->grInfoParams.engineInfo[grIdx].infoList,
844                     NV0080_CTRL_GR_INFO_MAX_SIZE * sizeof(*pVSI->grInfoParams.engineInfo[grIdx].infoList));
845 
846         portMemCopy(&pPrivate->staticInfo.globalSmOrder, sizeof(pPrivate->staticInfo.globalSmOrder),
847                     &pVSI->globalSmOrder.globalSmOrder[grIdx], sizeof(pVSI->globalSmOrder.globalSmOrder[grIdx]));
848 
849         // grCaps are the same for all GR and can be copied from VGPU static info
850         portMemCopy(pPrivate->staticInfo.grCaps.capsTbl, sizeof(pPrivate->staticInfo.grCaps.capsTbl),
851                     pVSI->grCapsBits, sizeof(pVSI->grCapsBits));
852 
853         // Initialize PDB properties synchronized with physical RM
854         pPrivate->staticInfo.pdbTable.bPerSubCtxheaderSupported = pVSI->bPerSubCtxheaderSupported;
855         kgraphicsSetPerSubcontextContextHeaderSupported(pGpu, pKernelGraphics, pPrivate->staticInfo.pdbTable.bPerSubCtxheaderSupported);
856 
857         pPrivate->staticInfo.pSmIssueRateModifier =
858                 portMemAllocNonPaged(sizeof(*pPrivate->staticInfo.pSmIssueRateModifier));
859         if (pPrivate->staticInfo.pSmIssueRateModifier == NULL)
860         {
861             status = NV_ERR_NO_MEMORY;
862             goto cleanup;
863         }
864 
865         portMemCopy(pPrivate->staticInfo.pSmIssueRateModifier, sizeof(*pPrivate->staticInfo.pSmIssueRateModifier),
866                     &pVSI->smIssueRateModifier.smIssueRateModifier[grIdx], sizeof(pVSI->smIssueRateModifier.smIssueRateModifier[grIdx]));
867 
868         pPrivate->staticInfo.pPpcMasks = portMemAllocNonPaged(sizeof(*pPrivate->staticInfo.pPpcMasks));
869         if (pPrivate->staticInfo.pPpcMasks == NULL)
870         {
871             status = NV_ERR_NO_MEMORY;
872             goto cleanup;
873         }
874 
875         portMemCopy(pPrivate->staticInfo.pPpcMasks, sizeof(*pPrivate->staticInfo.pPpcMasks),
876                     &pVSI->ppcMaskParams.enginePpcMasks[grIdx], sizeof(pVSI->ppcMaskParams.enginePpcMasks[grIdx]));
877 
878         portMemCopy(&pPrivate->staticInfo.floorsweepingMasks, sizeof(pPrivate->staticInfo.floorsweepingMasks),
879                     &pVSI->floorsweepMaskParams.floorsweepingMasks[grIdx], sizeof(pVSI->floorsweepMaskParams.floorsweepingMasks[grIdx]));
880 
881         pPrivate->staticInfo.pContextBuffersInfo =
882             portMemAllocNonPaged(sizeof(*pPrivate->staticInfo.pContextBuffersInfo));
883 
884         if (pPrivate->staticInfo.pContextBuffersInfo == NULL)
885         {
886             status = NV_ERR_NO_MEMORY;
887             goto cleanup;
888         }
889 
890         portMemCopy(pPrivate->staticInfo.pContextBuffersInfo,
891                     sizeof(*pPrivate->staticInfo.pContextBuffersInfo),
892                     &pVSI->ctxBuffInfo.engineContextBuffersInfo[grIdx],
893                     sizeof(pVSI->ctxBuffInfo.engineContextBuffersInfo[grIdx]));
894 
895         pPrivate->staticInfo.fecsRecordSize.fecsRecordSize = pVSI->fecsRecordSize.fecsRecordSize[grIdx].fecsRecordSize;
896 
897         pPrivate->staticInfo.pFecsTraceDefines =
898                 portMemAllocNonPaged(sizeof(*pPrivate->staticInfo.pFecsTraceDefines));
899 
900         if (pPrivate->staticInfo.pFecsTraceDefines == NULL)
901         {
902             status = NV_ERR_NO_MEMORY;
903             goto cleanup;
904         }
905 
906         portMemCopy(pPrivate->staticInfo.pFecsTraceDefines,
907                     sizeof(*pPrivate->staticInfo.pFecsTraceDefines),
908                     &pVSI->fecsTraceDefines.fecsTraceDefines[grIdx],
909                     sizeof(pVSI->fecsTraceDefines.fecsTraceDefines[grIdx]));
910 
911         portMemCopy(&pPrivate->staticInfo.pdbTable, sizeof(pPrivate->staticInfo.pdbTable),
912                     &pVSI->pdbTableParams.pdbTable[grIdx], sizeof(pVSI->pdbTableParams.pdbTable[grIdx]));
913     }
914     else if (grIdx == 0)
915     {
916         portMemCopy(pPrivate->staticInfo.grCaps.capsTbl, sizeof(pPrivate->staticInfo.grCaps.capsTbl),
917                     pVSI->grCapsBits, sizeof(pVSI->grCapsBits));
918 
919         pPrivate->staticInfo.pGrInfo = portMemAllocNonPaged(sizeof(*pPrivate->staticInfo.pGrInfo));
920         if (pPrivate->staticInfo.pGrInfo == NULL)
921         {
922             status = NV_ERR_NO_MEMORY;
923             goto cleanup;
924         }
925 
926         portMemCopy(pPrivate->staticInfo.pGrInfo->infoList,
927                     NV0080_CTRL_GR_INFO_MAX_SIZE * sizeof(*pPrivate->staticInfo.pGrInfo->infoList),
928                     pVSI->grInfoParams.engineInfo[grIdx].infoList,
929                     NV0080_CTRL_GR_INFO_MAX_SIZE * sizeof(*pVSI->grInfoParams.engineInfo[grIdx].infoList));
930 
931         // Initialize PDB properties synchronized with physical RM
932         pPrivate->staticInfo.pdbTable.bPerSubCtxheaderSupported = pVSI->bPerSubCtxheaderSupported;
933         kgraphicsSetPerSubcontextContextHeaderSupported(pGpu, pKernelGraphics, pPrivate->staticInfo.pdbTable.bPerSubCtxheaderSupported);
934 
935         portMemCopy(&pPrivate->staticInfo.globalSmOrder, sizeof(pPrivate->staticInfo.globalSmOrder),
936                     &pVSI->globalSmOrder.globalSmOrder[grIdx], sizeof(pVSI->globalSmOrder.globalSmOrder[grIdx]));
937 
938         pPrivate->staticInfo.pSmIssueRateModifier =
939                 portMemAllocNonPaged(sizeof(*pPrivate->staticInfo.pSmIssueRateModifier));
940         if (pPrivate->staticInfo.pSmIssueRateModifier == NULL)
941         {
942             status = NV_ERR_NO_MEMORY;
943             goto cleanup;
944         }
945 
946         portMemCopy(pPrivate->staticInfo.pSmIssueRateModifier, sizeof(*pPrivate->staticInfo.pSmIssueRateModifier),
947                     &pVSI->smIssueRateModifier.smIssueRateModifier[grIdx], sizeof(pVSI->smIssueRateModifier.smIssueRateModifier[grIdx]));
948 
949         pPrivate->staticInfo.pPpcMasks = portMemAllocNonPaged(sizeof(*pPrivate->staticInfo.pPpcMasks));
950         if (pPrivate->staticInfo.pPpcMasks == NULL)
951         {
952             status = NV_ERR_NO_MEMORY;
953             goto cleanup;
954         }
955 
956         portMemCopy(pPrivate->staticInfo.pPpcMasks, sizeof(*pPrivate->staticInfo.pPpcMasks),
957                     &pVSI->ppcMaskParams.enginePpcMasks[grIdx], sizeof(pVSI->ppcMaskParams.enginePpcMasks[grIdx]));
958 
959         pPrivate->staticInfo.pContextBuffersInfo =
960             portMemAllocNonPaged(sizeof(*pPrivate->staticInfo.pContextBuffersInfo));
961 
962         if (pPrivate->staticInfo.pContextBuffersInfo == NULL)
963         {
964             status = NV_ERR_NO_MEMORY;
965             goto cleanup;
966         }
967 
968         portMemCopy(pPrivate->staticInfo.pContextBuffersInfo,
969                     sizeof(*pPrivate->staticInfo.pContextBuffersInfo),
970                     &pVSI->ctxBuffInfo.engineContextBuffersInfo[grIdx],
971                     sizeof(pVSI->ctxBuffInfo.engineContextBuffersInfo[grIdx]));
972 
973         portMemCopy(&pPrivate->staticInfo.floorsweepingMasks, sizeof(pPrivate->staticInfo.floorsweepingMasks),
974                     &pVSI->floorsweepMaskParams.floorsweepingMasks[grIdx], sizeof(pVSI->floorsweepMaskParams.floorsweepingMasks[grIdx]));
975 
976         pPrivate->staticInfo.pRopInfo = portMemAllocNonPaged(sizeof(*pPrivate->staticInfo.pRopInfo));
977         if (pPrivate->staticInfo.pRopInfo == NULL)
978         {
979             status = NV_ERR_NO_MEMORY;
980             goto cleanup;
981         }
982 
983         portMemCopy(pPrivate->staticInfo.pRopInfo, sizeof(*pPrivate->staticInfo.pRopInfo),
984                     &pVSI->ropInfoParams.engineRopInfo[grIdx], sizeof(pVSI->ropInfoParams.engineRopInfo[grIdx]));
985 
986         pPrivate->staticInfo.pZcullInfo = portMemAllocNonPaged(sizeof(*pPrivate->staticInfo.pZcullInfo));
987         if (pPrivate->staticInfo.pZcullInfo == NULL)
988         {
989             status = NV_ERR_NO_MEMORY;
990             goto cleanup;
991         }
992 
993         portMemCopy(pPrivate->staticInfo.pZcullInfo, sizeof(*pPrivate->staticInfo.pZcullInfo),
994                     &pVSI->zcullInfoParams.engineZcullInfo[grIdx], sizeof(pVSI->zcullInfoParams.engineZcullInfo[grIdx]));
995 
996         pPrivate->staticInfo.fecsRecordSize.fecsRecordSize = pVSI->fecsRecordSize.fecsRecordSize[grIdx].fecsRecordSize;
997 
998         pPrivate->staticInfo.pFecsTraceDefines =
999                 portMemAllocNonPaged(sizeof(*pPrivate->staticInfo.pFecsTraceDefines));
1000         if (pPrivate->staticInfo.pFecsTraceDefines == NULL)
1001         {
1002             status = NV_ERR_NO_MEMORY;
1003             goto cleanup;
1004         }
1005 
1006         portMemCopy(pPrivate->staticInfo.pFecsTraceDefines,
1007                     sizeof(*pPrivate->staticInfo.pFecsTraceDefines),
1008                     &pVSI->fecsTraceDefines.fecsTraceDefines[grIdx],
1009                     sizeof(pVSI->fecsTraceDefines.fecsTraceDefines[grIdx]));
1010 
1011         portMemCopy(&pPrivate->staticInfo.pdbTable, sizeof(pPrivate->staticInfo.pdbTable),
1012                     &pVSI->pdbTableParams.pdbTable[grIdx], sizeof(pVSI->pdbTableParams.pdbTable[grIdx]));
1013     }
1014     else
1015     {
1016         // if MIG disabled, only GR0 static data needs to be published
1017         return status;
1018     }
1019 
1020     if (status == NV_OK)
1021     {
1022         // Publish static configuration
1023         pPrivate->bInitialized = NV_TRUE;
1024     }
1025 
1026     if (!IS_MIG_IN_USE(pGpu) && (grIdx == 0))
1027     {
1028         KernelGraphicsManager *pKernelGraphicsManager = GPU_GET_KERNEL_GRAPHICS_MANAGER(pGpu);
1029 
1030         // Cache legacy GR mask info (i.e. GR0 with MIG disabled) to pKernelGraphicsManager->legacyFsMaskState
1031         kgrmgrSetLegacyKgraphicsStaticInfo(pGpu, pKernelGraphicsManager, pKernelGraphics);
1032     }
1033 
1034 cleanup :
1035 
1036     if (status != NV_OK)
1037     {
1038         portMemFree(pPrivate->staticInfo.pGrInfo);
1039         pPrivate->staticInfo.pGrInfo = NULL;
1040 
1041         portMemFree(pPrivate->staticInfo.pPpcMasks);
1042         pPrivate->staticInfo.pPpcMasks = NULL;
1043 
1044         portMemFree(pPrivate->staticInfo.pZcullInfo);
1045         pPrivate->staticInfo.pZcullInfo = NULL;
1046 
1047         portMemFree(pPrivate->staticInfo.pRopInfo);
1048         pPrivate->staticInfo.pRopInfo = NULL;
1049 
1050         portMemFree(pPrivate->staticInfo.pContextBuffersInfo);
1051         pPrivate->staticInfo.pContextBuffersInfo = NULL;
1052 
1053         portMemFree(pPrivate->staticInfo.pSmIssueRateModifier);
1054         pPrivate->staticInfo.pSmIssueRateModifier = NULL;
1055 
1056         portMemFree(pPrivate->staticInfo.pFecsTraceDefines);
1057         pPrivate->staticInfo.pFecsTraceDefines = NULL;
1058     }
1059 
1060     return status;
1061 }
1062 
1063 NV_STATUS
kgraphicsLoadStaticInfo_KERNEL(OBJGPU * pGpu,KernelGraphics * pKernelGraphics,NvU32 swizzId)1064 kgraphicsLoadStaticInfo_KERNEL
1065 (
1066     OBJGPU *pGpu,
1067     KernelGraphics *pKernelGraphics,
1068     NvU32 swizzId
1069 )
1070 {
1071     KGRAPHICS_PRIVATE_DATA *pPrivate = pKernelGraphics->pPrivate;
1072     NvHandle hClient = NV01_NULL_OBJECT;
1073     NvHandle hDevice;
1074     NvHandle hSubdevice;
1075     RM_API *pRmApi = rmapiGetInterface(RMAPI_GPU_LOCK_INTERNAL);
1076     NvU32 grIdx = pKernelGraphics->instance;
1077     NV_STATUS status = NV_OK;
1078     NvBool bBcState = gpumgrGetBcEnabledStatus(pGpu);
1079     union
1080     {
1081         NV2080_CTRL_INTERNAL_STATIC_GR_GET_CAPS_PARAMS                   caps;
1082         NV2080_CTRL_INTERNAL_STATIC_GR_GET_INFO_PARAMS                   info;
1083         NV2080_CTRL_INTERNAL_STATIC_GR_GET_GLOBAL_SM_ORDER_PARAMS        globalSmOrder;
1084         NV2080_CTRL_INTERNAL_STATIC_GR_GET_FLOORSWEEPING_MASKS_PARAMS    floorsweepingMasks;
1085         NV2080_CTRL_INTERNAL_STATIC_GR_GET_PPC_MASKS_PARAMS              ppcMasks;
1086         NV2080_CTRL_INTERNAL_STATIC_GR_GET_ZCULL_INFO_PARAMS             zcullInfo;
1087         NV2080_CTRL_INTERNAL_STATIC_GR_GET_ROP_INFO_PARAMS               ropInfo;
1088         NV2080_CTRL_INTERNAL_STATIC_GR_GET_SM_ISSUE_RATE_MODIFIER_PARAMS smIssueRateModifier;
1089         NV2080_CTRL_INTERNAL_STATIC_GR_GET_FECS_RECORD_SIZE_PARAMS       fecsRecordSize;
1090         NV2080_CTRL_INTERNAL_STATIC_GR_GET_FECS_TRACE_DEFINES_PARAMS     fecsTraceDefines;
1091         NV2080_CTRL_INTERNAL_STATIC_GR_GET_PDB_PROPERTIES_PARAMS         pdbProperties;
1092     } *pParams = NULL;
1093 
1094     NV_ASSERT_OR_RETURN(pPrivate != NULL, NV_ERR_INVALID_STATE);
1095 
1096     if (pPrivate->bInitialized)
1097         return NV_OK;
1098 
1099     status = _kgraphicsInternalClientAlloc(pGpu, pKernelGraphics, swizzId, &hClient, &hDevice, &hSubdevice);
1100 
1101     if (status == NV_ERR_NOT_READY)
1102     {
1103         return NV_OK;
1104     }
1105     NV_ASSERT_OR_RETURN(status == NV_OK, status);
1106     NV_ASSERT_OR_RETURN(hClient != NV01_NULL_OBJECT, NV_ERR_INVALID_STATE);
1107 
1108     pParams = portMemAllocNonPaged(sizeof(*pParams));
1109     if (pParams == NULL)
1110     {
1111         status = NV_ERR_NO_MEMORY;
1112         goto cleanup;
1113     }
1114 
1115     if (IS_MIG_IN_USE(pGpu))
1116     {
1117         KernelMIGManager *pKernelMIGManager = GPU_GET_KERNEL_MIG_MANAGER(pGpu);
1118         MIG_INSTANCE_REF ref;
1119         RM_ENGINE_TYPE localRmEngineType;
1120         RsClient *pClient;
1121         Device *pDevice;
1122 
1123         NV_CHECK_OK_OR_GOTO(
1124             status,
1125             LEVEL_ERROR,
1126             serverGetClientUnderLock(&g_resServ, hClient, &pClient),
1127             cleanup);
1128 
1129         NV_CHECK_OK_OR_GOTO(
1130             status,
1131             LEVEL_ERROR,
1132             deviceGetByHandle(pClient, hDevice, &pDevice),
1133             cleanup);
1134 
1135         // Physical RM will fill with local indices, so localize the index
1136         NV_CHECK_OK_OR_GOTO(
1137             status,
1138             LEVEL_ERROR,
1139             kmigmgrGetInstanceRefFromDevice(pGpu, pKernelMIGManager, pDevice, &ref),
1140             cleanup);
1141         NV_CHECK_OK_OR_GOTO(
1142             status,
1143             LEVEL_ERROR,
1144             kmigmgrGetGlobalToLocalEngineType(pGpu, pKernelMIGManager, ref,
1145                                               RM_ENGINE_TYPE_GR(grIdx),
1146                                               &localRmEngineType),
1147             cleanup);
1148         grIdx = RM_ENGINE_TYPE_GR_IDX(localRmEngineType);
1149     }
1150 
1151     // GR Caps
1152     portMemSet(pParams, 0, sizeof(*pParams));
1153     NV_CHECK_OK_OR_GOTO(
1154         status,
1155         LEVEL_ERROR,
1156         pRmApi->Control(pRmApi,
1157                         hClient,
1158                         hSubdevice,
1159                         NV2080_CTRL_CMD_INTERNAL_STATIC_KGR_GET_CAPS,
1160                         pParams,
1161                         sizeof(pParams->caps)),
1162         cleanup);
1163 
1164     portMemCopy(&pPrivate->staticInfo.grCaps, sizeof(pPrivate->staticInfo.grCaps),
1165                 &pParams->caps.engineCaps[grIdx], sizeof(pParams->caps.engineCaps[grIdx]));
1166 
1167     // GR Info
1168     portMemSet(pParams, 0, sizeof(*pParams));
1169     status = pRmApi->Control(pRmApi,
1170                              hClient,
1171                              hSubdevice,
1172                              NV2080_CTRL_CMD_INTERNAL_STATIC_KGR_GET_INFO,
1173                              pParams,
1174                              sizeof(pParams->info));
1175 
1176     if (status == NV_OK)
1177     {
1178         pPrivate->staticInfo.pGrInfo = portMemAllocNonPaged(sizeof(*pPrivate->staticInfo.pGrInfo));
1179         if (pPrivate->staticInfo.pGrInfo == NULL)
1180         {
1181             status = NV_ERR_NO_MEMORY;
1182             goto cleanup;
1183         }
1184 
1185         portMemCopy(pPrivate->staticInfo.pGrInfo->infoList,
1186                     NV0080_CTRL_GR_INFO_MAX_SIZE * sizeof(*pPrivate->staticInfo.pGrInfo->infoList),
1187                     pParams->info.engineInfo[grIdx].infoList,
1188                     NV0080_CTRL_GR_INFO_MAX_SIZE * sizeof(*pParams->info.engineInfo[grIdx].infoList));
1189 
1190     }
1191 
1192     // Floorsweeping masks
1193     portMemSet(pParams, 0, sizeof(*pParams));
1194     NV_CHECK_OK_OR_GOTO(
1195         status,
1196         LEVEL_ERROR,
1197         pRmApi->Control(pRmApi,
1198                         hClient,
1199                         hSubdevice,
1200                         NV2080_CTRL_CMD_INTERNAL_STATIC_KGR_GET_FLOORSWEEPING_MASKS,
1201                         pParams,
1202                         sizeof(pParams->floorsweepingMasks)),
1203         cleanup);
1204 
1205     portMemCopy(&pPrivate->staticInfo.floorsweepingMasks, sizeof(pPrivate->staticInfo.floorsweepingMasks),
1206                 &pParams->floorsweepingMasks.floorsweepingMasks[grIdx], sizeof(pParams->floorsweepingMasks.floorsweepingMasks[grIdx]));
1207 
1208     //
1209     // Most of GR is stub'd in AMODEL. However, some tests still need the CAPS/INFO data,
1210     // so we still need to generate CAPS/INFO data for AMODEL
1211     //
1212     if (IS_MODS_AMODEL(pGpu))
1213     {
1214         pPrivate->bInitialized = NV_TRUE;
1215         if (!IS_MIG_IN_USE(pGpu) && (grIdx == 0))
1216         {
1217             KernelGraphicsManager *pKernelGraphicsManager = GPU_GET_KERNEL_GRAPHICS_MANAGER(pGpu);
1218 
1219             // Cache legacy GR mask info (i.e. GR0 with MIG disabled) to pKernelGraphicsManager->legacyFsMaskState
1220             kgrmgrSetLegacyKgraphicsStaticInfo(pGpu, pKernelGraphicsManager, pKernelGraphics);
1221         }
1222         status = NV_OK;
1223         goto cleanup;
1224     }
1225 
1226     // GR Global SM Order
1227     portMemSet(pParams, 0, sizeof(*pParams));
1228     NV_CHECK_OK_OR_GOTO(status, LEVEL_ERROR,
1229         pRmApi->Control(pRmApi,
1230                         hClient,
1231                         hSubdevice,
1232                         NV2080_CTRL_CMD_INTERNAL_STATIC_KGR_GET_GLOBAL_SM_ORDER,
1233                         pParams,
1234                         sizeof(pParams->globalSmOrder)),
1235         cleanup);
1236 
1237     portMemCopy(&pPrivate->staticInfo.globalSmOrder, sizeof(pPrivate->staticInfo.globalSmOrder),
1238                 &pParams->globalSmOrder.globalSmOrder[grIdx], sizeof(pParams->globalSmOrder.globalSmOrder[grIdx]));
1239 
1240     // PPC Mask
1241     portMemSet(pParams, 0, sizeof(*pParams));
1242     status = pRmApi->Control(pRmApi,
1243                              hClient,
1244                              hSubdevice,
1245                              NV2080_CTRL_CMD_INTERNAL_STATIC_KGR_GET_PPC_MASKS,
1246                              pParams,
1247                              sizeof(pParams->ppcMasks));
1248 
1249     if (status == NV_OK)
1250     {
1251         pPrivate->staticInfo.pPpcMasks = portMemAllocNonPaged(sizeof(*pPrivate->staticInfo.pPpcMasks));
1252         if (pPrivate->staticInfo.pPpcMasks == NULL)
1253         {
1254             status = NV_ERR_NO_MEMORY;
1255             goto cleanup;
1256         }
1257 
1258         portMemCopy(pPrivate->staticInfo.pPpcMasks, sizeof(*pPrivate->staticInfo.pPpcMasks),
1259                     &pParams->ppcMasks.enginePpcMasks[grIdx], sizeof(pParams->ppcMasks.enginePpcMasks[grIdx]));
1260     }
1261     else if (status == NV_ERR_NOT_SUPPORTED)
1262     {
1263         //
1264         // Some chips don't support this call, so just keep the pPpcMasks
1265         // pointer as NULL, but don't return error
1266         //
1267         status = NV_OK;
1268     }
1269 
1270     portMemSet(pParams, 0, sizeof(*pParams));
1271     status = pRmApi->Control(pRmApi,
1272                              hClient,
1273                              hSubdevice,
1274                              NV2080_CTRL_CMD_INTERNAL_STATIC_KGR_GET_ZCULL_INFO,
1275                              pParams,
1276                              sizeof(pParams->zcullInfo));
1277 
1278     if (status == NV_OK)
1279     {
1280         pPrivate->staticInfo.pZcullInfo = portMemAllocNonPaged(sizeof(*pPrivate->staticInfo.pZcullInfo));
1281         if (pPrivate->staticInfo.pZcullInfo == NULL)
1282         {
1283             status = NV_ERR_NO_MEMORY;
1284             goto cleanup;
1285         }
1286 
1287         portMemCopy(pPrivate->staticInfo.pZcullInfo, sizeof(*pPrivate->staticInfo.pZcullInfo),
1288                     &pParams->zcullInfo.engineZcullInfo[grIdx], sizeof(pParams->zcullInfo.engineZcullInfo[grIdx]));
1289     }
1290     else if (status == NV_ERR_NOT_SUPPORTED)
1291     {
1292         // It's expected to get this error when MIG is enabled, thus don't return error
1293         if (IS_MIG_ENABLED(pGpu))
1294         {
1295             status = NV_OK;
1296         }
1297     }
1298 
1299     // ROP Info
1300     portMemSet(pParams, 0, sizeof(*pParams));
1301     status = pRmApi->Control(pRmApi,
1302                              hClient,
1303                              hSubdevice,
1304                              NV2080_CTRL_CMD_INTERNAL_STATIC_KGR_GET_ROP_INFO,
1305                              pParams,
1306                              sizeof(pParams->ropInfo));
1307 
1308     if (status == NV_OK)
1309     {
1310         pPrivate->staticInfo.pRopInfo = portMemAllocNonPaged(sizeof(*pPrivate->staticInfo.pRopInfo));
1311         if (pPrivate->staticInfo.pRopInfo == NULL)
1312         {
1313             status = NV_ERR_NO_MEMORY;
1314             goto cleanup;
1315         }
1316 
1317         portMemCopy(pPrivate->staticInfo.pRopInfo, sizeof(*pPrivate->staticInfo.pRopInfo),
1318                     &pParams->ropInfo.engineRopInfo[grIdx], sizeof(pParams->ropInfo.engineRopInfo[grIdx]));
1319     }
1320     else if (status == NV_ERR_NOT_SUPPORTED)
1321     {
1322         // It's expected to get this error when MIG is enabled, thus don't return error
1323         if (IS_MIG_ENABLED(pGpu))
1324         {
1325             status = NV_OK;
1326         }
1327     }
1328 
1329     // SM Issue Rate Modifier
1330     portMemSet(pParams, 0, sizeof(*pParams));
1331     status = pRmApi->Control(pRmApi,
1332                              hClient,
1333                              hSubdevice,
1334                              NV2080_CTRL_CMD_INTERNAL_STATIC_KGR_GET_SM_ISSUE_RATE_MODIFIER,
1335                              pParams,
1336                              sizeof(pParams->smIssueRateModifier));
1337 
1338     if (status == NV_OK)
1339     {
1340         pPrivate->staticInfo.pSmIssueRateModifier = portMemAllocNonPaged(sizeof(*pPrivate->staticInfo.pSmIssueRateModifier));
1341         if (pPrivate->staticInfo.pSmIssueRateModifier == NULL)
1342         {
1343             status = NV_ERR_NO_MEMORY;
1344             goto cleanup;
1345         }
1346 
1347         portMemCopy(pPrivate->staticInfo.pSmIssueRateModifier, sizeof(*pPrivate->staticInfo.pSmIssueRateModifier),
1348                     &pParams->smIssueRateModifier.smIssueRateModifier[grIdx], sizeof(pParams->smIssueRateModifier.smIssueRateModifier[grIdx]));
1349     }
1350     else if (status == NV_ERR_NOT_SUPPORTED)
1351     {
1352         status = NV_OK;
1353     }
1354 
1355     // FECS Record Size
1356     portMemSet(pParams, 0, sizeof(*pParams));
1357     NV_CHECK_OK_OR_GOTO(status, LEVEL_ERROR,
1358         pRmApi->Control(pRmApi,
1359                         hClient,
1360                         hSubdevice,
1361                         NV2080_CTRL_CMD_INTERNAL_STATIC_KGR_GET_FECS_RECORD_SIZE,
1362                         pParams,
1363                         sizeof(pParams->fecsRecordSize)),
1364         cleanup);
1365 
1366     pPrivate->staticInfo.fecsRecordSize.fecsRecordSize = pParams->fecsRecordSize.fecsRecordSize[grIdx].fecsRecordSize;
1367 
1368     // FECS Trace Defines
1369     portMemSet(pParams, 0, sizeof(*pParams));
1370     status = pRmApi->Control(pRmApi,
1371                         hClient,
1372                         hSubdevice,
1373                         NV2080_CTRL_CMD_INTERNAL_STATIC_KGR_GET_FECS_TRACE_DEFINES,
1374                         pParams,
1375                         sizeof(pParams->fecsTraceDefines));
1376     if (status == NV_OK)
1377     {
1378         pPrivate->staticInfo.pFecsTraceDefines = portMemAllocNonPaged(sizeof(*pPrivate->staticInfo.pFecsTraceDefines));
1379         if (pPrivate->staticInfo.pFecsTraceDefines == NULL)
1380         {
1381             status = NV_ERR_NO_MEMORY;
1382             goto cleanup;
1383         }
1384         portMemCopy(pPrivate->staticInfo.pFecsTraceDefines, sizeof(*pPrivate->staticInfo.pFecsTraceDefines),
1385                     &pParams->fecsTraceDefines.fecsTraceDefines[grIdx], sizeof(pParams->fecsTraceDefines.fecsTraceDefines[grIdx]));
1386     }
1387     else if (status == NV_ERR_NOT_SUPPORTED)
1388     {
1389         status = NV_OK;
1390     }
1391 
1392     // PDB Properties
1393     portMemSet(pParams, 0, sizeof(*pParams));
1394     NV_CHECK_OK_OR_GOTO(
1395         status,
1396         LEVEL_ERROR,
1397         pRmApi->Control(pRmApi,
1398                         hClient,
1399                         hSubdevice,
1400                         NV2080_CTRL_CMD_INTERNAL_STATIC_KGR_GET_PDB_PROPERTIES,
1401                         pParams,
1402                         sizeof(pParams->pdbProperties)),
1403         cleanup);
1404 
1405     portMemCopy(&pPrivate->staticInfo.pdbTable, sizeof(pPrivate->staticInfo.pdbTable),
1406                 &pParams->pdbProperties.pdbTable[grIdx], sizeof(pParams->pdbProperties.pdbTable[grIdx]));
1407     kgraphicsSetPerSubcontextContextHeaderSupported(pGpu, pKernelGraphics, pPrivate->staticInfo.pdbTable.bPerSubCtxheaderSupported);
1408 
1409     // Publish static configuration
1410     pPrivate->bInitialized = NV_TRUE;
1411 
1412     // The deferred data is ready after MIG is enabled, so no need to defer the initialization
1413     if (IS_MIG_IN_USE(pGpu) ||
1414         !kgraphicsShouldDeferContextInit(pGpu, pKernelGraphics))
1415     {
1416         NV_CHECK_OK_OR_GOTO(status, LEVEL_ERROR,
1417             kgraphicsInitializeDeferredStaticData(pGpu, pKernelGraphics, hClient, hSubdevice), cleanup);
1418     }
1419 
1420     if (!IS_MIG_IN_USE(pGpu) && (grIdx == 0))
1421     {
1422         KernelGraphicsManager *pKernelGraphicsManager = GPU_GET_KERNEL_GRAPHICS_MANAGER(pGpu);
1423 
1424         // Cache legacy GR mask info (i.e. GR0 with MIG disabled) to pKernelGraphicsManager->legacyFsMaskState
1425         kgrmgrSetLegacyKgraphicsStaticInfo(pGpu, pKernelGraphicsManager, pKernelGraphics);
1426     }
1427 
1428 cleanup:
1429     if (status != NV_OK)
1430     {
1431         // Redact static configuration
1432         pPrivate->bInitialized = NV_FALSE;
1433 
1434         portMemFree(pPrivate->staticInfo.pGrInfo);
1435         pPrivate->staticInfo.pGrInfo = NULL;
1436 
1437         portMemFree(pPrivate->staticInfo.pPpcMasks);
1438         pPrivate->staticInfo.pPpcMasks = NULL;
1439 
1440         portMemFree(pPrivate->staticInfo.pZcullInfo);
1441         pPrivate->staticInfo.pZcullInfo = NULL;
1442 
1443         portMemFree(pPrivate->staticInfo.pRopInfo);
1444         pPrivate->staticInfo.pRopInfo = NULL;
1445 
1446         portMemFree(pPrivate->staticInfo.pContextBuffersInfo);
1447         pPrivate->staticInfo.pContextBuffersInfo = NULL;
1448 
1449         portMemFree(pPrivate->staticInfo.pSmIssueRateModifier);
1450         pPrivate->staticInfo.pSmIssueRateModifier = NULL;
1451 
1452         portMemFree(pPrivate->staticInfo.pFecsTraceDefines);
1453         pPrivate->staticInfo.pFecsTraceDefines = NULL;
1454     }
1455 
1456     // If we had to subscribe specifically, free the hclient we allocated
1457     if (hClient != NV01_NULL_OBJECT)
1458         pRmApi->Free(pRmApi, hClient, hClient);
1459 
1460     if (gpumgrGetBcEnabledStatus(pGpu) != bBcState)
1461     {
1462         // Corrupted broadcast state!
1463         NV_ASSERT(gpumgrGetBcEnabledStatus(pGpu) != bBcState);
1464         gpumgrSetBcEnabledStatus(pGpu, bBcState);
1465     }
1466 
1467     portMemFree(pParams);
1468 
1469     return status;
1470 }
1471 
1472 /*! Return if GFX is supported for the given kernel graphics engine */
1473 NvBool
kgraphicsIsGFXSupported_IMPL(OBJGPU * pGpu,KernelGraphics * pKernelGraphics)1474 kgraphicsIsGFXSupported_IMPL
1475 (
1476     OBJGPU *pGpu,
1477     KernelGraphics *pKernelGraphics
1478 )
1479 {
1480     const KGRAPHICS_STATIC_INFO *pKernelGraphicsStaticInfo = kgraphicsGetStaticInfo(pGpu, pKernelGraphics);
1481     NvU32 gfxCapabilites;
1482 
1483     NV_ASSERT_OR_RETURN(pKernelGraphicsStaticInfo != NULL, NV_FALSE);
1484     NV_ASSERT_OR_RETURN(pKernelGraphicsStaticInfo->pGrInfo != NULL, NV_FALSE);
1485 
1486     gfxCapabilites = pKernelGraphicsStaticInfo->pGrInfo->infoList[NV2080_CTRL_GR_INFO_INDEX_GFX_CAPABILITIES].data;
1487 
1488     return (FLD_TEST_DRF(2080_CTRL_GR, _INFO_GFX_CAPABILITIES, _2D, _TRUE, gfxCapabilites) &&
1489             FLD_TEST_DRF(2080_CTRL_GR, _INFO_GFX_CAPABILITIES, _3D, _TRUE, gfxCapabilites) &&
1490             FLD_TEST_DRF(2080_CTRL_GR, _INFO_GFX_CAPABILITIES, _I2M, _TRUE, gfxCapabilites));
1491 }
1492 
1493 /*! Retrieve ctxbufpool parameters for given local ctx buffer */
1494 const CTX_BUF_INFO *
kgraphicsGetCtxBufferInfo_IMPL(OBJGPU * pGpu,KernelGraphics * pKernelGraphics,GR_CTX_BUFFER buf)1495 kgraphicsGetCtxBufferInfo_IMPL
1496 (
1497     OBJGPU *pGpu,
1498     KernelGraphics *pKernelGraphics,
1499     GR_CTX_BUFFER buf
1500 )
1501 {
1502     NV_ASSERT_OR_RETURN(NV_ENUM_IS(GR_CTX_BUFFER, buf), NULL);
1503     return &pKernelGraphics->maxCtxBufSize[buf];
1504 }
1505 
1506 /*! Set ctxbufpool parameters for given local ctx buffer */
1507 void
kgraphicsSetCtxBufferInfo_IMPL(OBJGPU * pGpu,KernelGraphics * pKernelGraphics,GR_CTX_BUFFER buf,NvU64 size,NvU64 align,RM_ATTR_PAGE_SIZE attr,NvBool bContiguous)1508 kgraphicsSetCtxBufferInfo_IMPL
1509 (
1510     OBJGPU *pGpu,
1511     KernelGraphics *pKernelGraphics,
1512     GR_CTX_BUFFER buf,
1513     NvU64 size,
1514     NvU64 align,
1515     RM_ATTR_PAGE_SIZE attr,
1516     NvBool bContiguous
1517 )
1518 {
1519     CTX_BUF_INFO *pInfo;
1520     NV_ASSERT_OR_RETURN_VOID(NV_ENUM_IS(GR_CTX_BUFFER, buf));
1521 
1522     pInfo = &pKernelGraphics->maxCtxBufSize[buf];
1523     pInfo->size    = size;
1524     pInfo->align   = align;
1525     pInfo->attr    = attr;
1526     pInfo->bContig = bContiguous;
1527 }
1528 
1529 /*! Clear ctxbufpool parameters for all local ctx buffers */
1530 void
kgraphicsClearCtxBufferInfo_IMPL(OBJGPU * pGpu,KernelGraphics * pKernelGraphics)1531 kgraphicsClearCtxBufferInfo_IMPL
1532 (
1533     OBJGPU *pGpu,
1534     KernelGraphics *pKernelGraphics
1535 )
1536 {
1537     portMemSet(pKernelGraphics->maxCtxBufSize, 0, sizeof(pKernelGraphics->maxCtxBufSize));
1538 }
1539 
1540 /*! Initialize ctxbufpool for this engine */
1541 NV_STATUS
kgraphicsInitCtxBufPool_IMPL(OBJGPU * pGpu,KernelGraphics * pKernelGraphics,Heap * pHeap)1542 kgraphicsInitCtxBufPool_IMPL
1543 (
1544     OBJGPU *pGpu,
1545     KernelGraphics *pKernelGraphics,
1546     Heap *pHeap
1547 )
1548 {
1549     return ctxBufPoolInit(pGpu, pHeap, &pKernelGraphics->pCtxBufPool);
1550 }
1551 
1552 /*! Retrieve ctxbufpool for this engine */
1553 CTX_BUF_POOL_INFO *
kgraphicsGetCtxBufPool_IMPL(OBJGPU * pGpu,KernelGraphics * pKernelGraphics)1554 kgraphicsGetCtxBufPool_IMPL
1555 (
1556     OBJGPU *pGpu,
1557     KernelGraphics *pKernelGraphics
1558 )
1559 {
1560     return pKernelGraphics->pCtxBufPool;
1561 }
1562 
1563 /*! destroy ctxbufpool for this engine */
1564 void
kgraphicsDestroyCtxBufPool_IMPL(OBJGPU * pGpu,KernelGraphics * pKernelGraphics)1565 kgraphicsDestroyCtxBufPool_IMPL
1566 (
1567     OBJGPU *pGpu,
1568     KernelGraphics *pKernelGraphics
1569 )
1570 {
1571     if (pKernelGraphics->pCtxBufPool == NULL)
1572         return;
1573 
1574     ctxBufPoolRelease(pKernelGraphics->pCtxBufPool);
1575     ctxBufPoolDestroy(&pKernelGraphics->pCtxBufPool);
1576     pKernelGraphics->pCtxBufPool = NULL;
1577 }
1578 
1579 /*! Get the global ctx buffers for the given GFID */
1580 GR_GLOBALCTX_BUFFERS *
kgraphicsGetGlobalCtxBuffers_IMPL(OBJGPU * pGpu,KernelGraphics * pKernelGraphics,NvU32 gfid)1581 kgraphicsGetGlobalCtxBuffers_IMPL
1582 (
1583     OBJGPU *pGpu,
1584     KernelGraphics *pKernelGraphics,
1585     NvU32 gfid
1586 )
1587 {
1588     if (pKernelGraphics->globalCtxBuffersInfo.pGlobalCtxBuffers == NULL)
1589         return NULL;
1590     return &pKernelGraphics->globalCtxBuffersInfo.pGlobalCtxBuffers[gfid];
1591 }
1592 
1593 /*! Should this global ctx buffer be mapped as size aligned? */
1594 NvBool
kgraphicsIsGlobalCtxBufferSizeAligned_IMPL(OBJGPU * pGpu,KernelGraphics * pKernelGraphics,GR_GLOBALCTX_BUFFER buf)1595 kgraphicsIsGlobalCtxBufferSizeAligned_IMPL
1596 (
1597     OBJGPU *pGpu,
1598     KernelGraphics *pKernelGraphics,
1599     GR_GLOBALCTX_BUFFER buf
1600 )
1601 {
1602     NV_ASSERT_OR_RETURN(NV_ENUM_IS(GR_GLOBALCTX_BUFFER, buf), NV_FALSE);
1603     return pKernelGraphics->globalCtxBuffersInfo.bSizeAligned[buf];
1604 }
1605 
1606 /*! Get ctx buf attr for global priv access map */
1607 const GR_BUFFER_ATTR *
kgraphicsGetGlobalPrivAccessMapAttr_IMPL(OBJGPU * pGpu,KernelGraphics * pKernelGraphics)1608 kgraphicsGetGlobalPrivAccessMapAttr_IMPL
1609 (
1610     OBJGPU *pGpu,
1611     KernelGraphics *pKernelGraphics
1612 )
1613 {
1614     return &pKernelGraphics->globalCtxBuffersInfo.globalCtxAttr[GR_GLOBAL_BUFFER_GLOBAL_PRIV_ACCESS_MAP];
1615 }
1616 
1617 /*
1618  * @brief Get Main context buffer size
1619  *
1620  * @param[in]  pGpu
1621  * @param[in]  pKernelGraphics
1622  * @param[in]  bIncludeSubctxHdrs If subctx headers should be included in size calculation
1623  * @param[out] pSize              Main Context buffer size
1624  */
1625 NV_STATUS
kgraphicsGetMainCtxBufferSize_IMPL(OBJGPU * pGpu,KernelGraphics * pKernelGraphics,NvBool bIncludeSubctxHdrs,NvU32 * pSize)1626 kgraphicsGetMainCtxBufferSize_IMPL
1627 (
1628     OBJGPU *pGpu,
1629     KernelGraphics *pKernelGraphics,
1630     NvBool bIncludeSubctxHdrs,
1631     NvU32 *pSize
1632 )
1633 {
1634     const KGRAPHICS_STATIC_INFO *pKernelGraphicsStaticInfo = kgraphicsGetStaticInfo(pGpu, pKernelGraphics);
1635     NvU32 size;
1636 
1637     NV_ASSERT_OR_RETURN(pKernelGraphicsStaticInfo != NULL, NV_ERR_INVALID_STATE);
1638     NV_ASSERT_OR_RETURN(pKernelGraphicsStaticInfo->pGrInfo != NULL, NV_ERR_INVALID_STATE);
1639     NV_ASSERT_OR_RETURN(pKernelGraphicsStaticInfo->pContextBuffersInfo != NULL, NV_ERR_INVALID_STATE);
1640 
1641     size = pKernelGraphicsStaticInfo->pContextBuffersInfo->engine[NV0080_CTRL_FIFO_GET_ENGINE_CONTEXT_PROPERTIES_ENGINE_ID_GRAPHICS].size;
1642 
1643     // Allocate space for per VEID headers in the golden context buffer.
1644     if (bIncludeSubctxHdrs &&
1645         kgraphicsIsPerSubcontextContextHeaderSupported(pGpu, pKernelGraphics))
1646     {
1647         // TODO size this down to max per-engine subcontexts
1648         NvU32 maxSubctx = pKernelGraphicsStaticInfo->pGrInfo->infoList[NV2080_CTRL_GR_INFO_INDEX_MAX_SUBCONTEXT_COUNT].data;
1649 
1650         // The header needs to start at a 4 KB aligned address
1651         size = RM_ALIGN_UP(size, RM_PAGE_SIZE);
1652 
1653         // The header is only 256 bytes; but needs to be 4KB aligned.
1654         size += (RM_PAGE_SIZE * maxSubctx);
1655     }
1656 
1657    *pSize = size;
1658     return NV_OK;
1659 }
1660 
1661 NV_STATUS
kgraphicsAllocKgraphicsBuffers_KERNEL(OBJGPU * pGpu,KernelGraphics * pKernelGraphics,KernelGraphicsContext * pKernelGraphicsContext,KernelChannel * pKernelChannel)1662 kgraphicsAllocKgraphicsBuffers_KERNEL
1663 (
1664     OBJGPU *pGpu,
1665     KernelGraphics *pKernelGraphics,
1666     KernelGraphicsContext *pKernelGraphicsContext,
1667     KernelChannel *pKernelChannel
1668 )
1669 {
1670     NvU32 gfid;
1671     OBJGVASPACE *pGVAS;
1672 
1673     NV_ASSERT_OR_RETURN(pKernelChannel != NULL, NV_ERR_INVALID_CHANNEL);
1674     pGVAS = dynamicCast(pKernelChannel->pVAS, OBJGVASPACE);
1675     gfid = kchannelGetGfid(pKernelChannel);
1676 
1677     // Deferred static info is necessary at this point for FECS buffer allocation. Skip for guest RM
1678     if (!IS_VIRTUAL(pGpu))
1679     {
1680         NV_CHECK_OK_OR_RETURN(LEVEL_ERROR,
1681             kgraphicsInitializeDeferredStaticData(pGpu, pKernelGraphics, NV01_NULL_OBJECT, NV01_NULL_OBJECT));
1682     }
1683 
1684     //
1685     // Allocate global context buffers for this gfid, if they haven't been
1686     // already
1687     //
1688     if (kgraphicsGetGlobalCtxBuffers(pGpu, pKernelGraphics, gfid)->memDesc[GR_GLOBALCTX_BUFFER_FECS_EVENT] == NULL)
1689     {
1690         NV_CHECK_OK_OR_RETURN(LEVEL_ERROR,
1691             kgraphicsAllocGlobalCtxBuffers_HAL(pGpu, pKernelGraphics, gfid));
1692     }
1693 
1694     if (kgraphicsIsCtxswLoggingSupported(pGpu, pKernelGraphics) &&
1695         (kgraphicsGetGlobalCtxBuffers(pGpu, pKernelGraphics, gfid)->memDesc[GR_GLOBALCTX_BUFFER_FECS_EVENT] != NULL))
1696     {
1697         KernelGraphicsManager *pKernelGraphicsManager = GPU_GET_KERNEL_GRAPHICS_MANAGER(pGpu);
1698 
1699         if (!gvaspaceIsExternallyOwned(pGVAS) && !IS_VIRTUAL_WITHOUT_SRIOV(pGpu))
1700         {
1701             //
1702             // We map CTXSW buffer on each object allocation including compute object
1703             // Other global context buffers are not mapped during compute object alloc with subcontexts since
1704             // those are GR-only buffers and not needed for compute-only contexts
1705             //
1706             _kgraphicsMapGlobalCtxBuffer(pGpu, pKernelGraphics, gfid, pKernelChannel->pVAS, pKernelGraphicsContext,
1707                                          GR_GLOBALCTX_BUFFER_FECS_EVENT, NV_FALSE);
1708         }
1709 
1710         if (!fecsBufferIsMapped(pGpu, pKernelGraphics))
1711         {
1712             fecsBufferMap(pGpu, pKernelGraphics);
1713         }
1714 
1715         if (fecsGetCtxswLogConsumerCount(pGpu, pKernelGraphicsManager) > 0)
1716             fecsBufferReset(pGpu, pKernelGraphics);
1717     }
1718 
1719     return NV_OK;
1720 }
1721 
1722 static NV_STATUS
_kgraphicsMapGlobalCtxBuffer(OBJGPU * pGpu,KernelGraphics * pKernelGraphics,NvU32 gfid,OBJVASPACE * pVAS,KernelGraphicsContext * pKernelGraphicsContext,GR_GLOBALCTX_BUFFER buffId,NvBool bIsReadOnly)1723 _kgraphicsMapGlobalCtxBuffer
1724 (
1725     OBJGPU *pGpu,
1726     KernelGraphics *pKernelGraphics,
1727     NvU32 gfid,
1728     OBJVASPACE *pVAS,
1729     KernelGraphicsContext *pKernelGraphicsContext,
1730     GR_GLOBALCTX_BUFFER buffId,
1731     NvBool bIsReadOnly
1732 )
1733 {
1734     KernelGraphicsContextUnicast *pKernelGraphicsContextUnicast;
1735     NV_STATUS status = NV_OK;
1736     NvU64 vaddr = 0;
1737     MEMORY_DESCRIPTOR *pMemDesc;
1738     NvBool bSizeAligned;
1739 
1740     NV_ASSERT_OK_OR_RETURN(
1741         kgrctxGetUnicast(pGpu, pKernelGraphicsContext, &pKernelGraphicsContextUnicast));
1742 
1743     bSizeAligned = pKernelGraphics->globalCtxBuffersInfo.bSizeAligned[buffId];
1744     pMemDesc = pKernelGraphics->globalCtxBuffersInfo.pGlobalCtxBuffers[gfid].memDesc[buffId];
1745 
1746     if (pMemDesc == NULL)
1747     {
1748         NvU32 buffSize;
1749         NvU32 fifoEngineId;
1750         const KGRAPHICS_STATIC_INFO *pKernelGraphicsStaticInfo;
1751 
1752         pKernelGraphicsStaticInfo = kgraphicsGetStaticInfo(pGpu, pKernelGraphics);
1753         NV_ASSERT_OR_RETURN(pKernelGraphicsStaticInfo != NULL, NV_ERR_INVALID_STATE);
1754         NV_ASSERT_OR_RETURN(pKernelGraphicsStaticInfo->pContextBuffersInfo != NULL, NV_ERR_INVALID_STATE);
1755 
1756         NV_ASSERT_OK_OR_RETURN(kgrctxGlobalCtxBufferToFifoEngineId(buffId, &fifoEngineId));
1757         buffSize = pKernelGraphicsStaticInfo->pContextBuffersInfo->engine[fifoEngineId].size;
1758         if (buffSize == 0)
1759         {
1760             NV_PRINTF(LEVEL_INFO,
1761                       "Could not map %s Buffer as buffer is not supported\n",
1762                       NV_ENUM_TO_STRING(GR_GLOBALCTX_BUFFER, buffId));
1763             return NV_OK;
1764         }
1765         else
1766         {
1767             NV_PRINTF(LEVEL_ERROR,
1768                       "Could not map %s Buffer, no memory allocated for it!\n",
1769                       NV_ENUM_TO_STRING(GR_GLOBALCTX_BUFFER, buffId));
1770             return NV_ERR_INVALID_ARGUMENT;
1771         }
1772     }
1773 
1774     // Unconditionally call map for refcounting
1775     NV_CHECK_OK_OR_RETURN(LEVEL_ERROR,
1776         kgraphicsMapCtxBuffer(pGpu, pKernelGraphics, pMemDesc, pVAS,
1777                               &pKernelGraphicsContextUnicast->globalCtxBufferVaList[buffId],
1778                               bSizeAligned,
1779                               bIsReadOnly));
1780 
1781     NV_ASSERT_OK(vaListFindVa(&pKernelGraphicsContextUnicast->globalCtxBufferVaList[buffId], pVAS, &vaddr));
1782 
1783     NV_PRINTF(LEVEL_INFO,
1784               "GPU:%d %s Buffer PA @ 0x%llx VA @ 0x%llx of Size 0x%llx\n",
1785               pGpu->gpuInstance, NV_ENUM_TO_STRING(GR_GLOBALCTX_BUFFER, buffId),
1786               memdescGetPhysAddr(memdescGetMemDescFromGpu(pMemDesc, pGpu), AT_GPU, 0),
1787               vaddr, pMemDesc->Size);
1788 
1789     return status;
1790 }
1791 
1792 /*!
1793  * @brief Map a GR ctx buffer
1794  */
1795 NV_STATUS
kgraphicsMapCtxBuffer_IMPL(OBJGPU * pGpu,KernelGraphics * pKernelGraphics,MEMORY_DESCRIPTOR * pMemDesc,OBJVASPACE * pVAS,VA_LIST * pVaList,NvBool bAlignSize,NvBool bIsReadOnly)1796 kgraphicsMapCtxBuffer_IMPL
1797 (
1798     OBJGPU *pGpu,
1799     KernelGraphics *pKernelGraphics,
1800     MEMORY_DESCRIPTOR *pMemDesc,
1801     OBJVASPACE *pVAS,
1802     VA_LIST *pVaList,
1803     NvBool bAlignSize,
1804     NvBool bIsReadOnly
1805 )
1806 {
1807     NV_STATUS status = NV_OK;
1808     NvU64 vaddr = 0;
1809     OBJGVASPACE *pGVAS;
1810 
1811     NV_ASSERT(!gpumgrGetBcEnabledStatus(pGpu));
1812 
1813     NV_PRINTF(LEVEL_INFO, "gpu:%d isBC=%d\n", pGpu->gpuInstance,
1814               gpumgrGetBcEnabledStatus(pGpu));
1815 
1816     pGVAS = dynamicCast(pVAS, OBJGVASPACE);
1817     NV_ASSERT_OR_RETURN(!gvaspaceIsExternallyOwned(pGVAS), NV_ERR_INVALID_OPERATION);
1818 
1819     status = vaListFindVa(pVaList, pVAS, &vaddr);
1820     if (status == NV_ERR_OBJECT_NOT_FOUND)
1821     {
1822         // create a new subcontext mapping
1823         NvU32 allocFlags  = bAlignSize ? DMA_ALLOC_VASPACE_SIZE_ALIGNED : DMA_ALLOC_VASPACE_NONE;
1824         NvU32 updateFlags = bIsReadOnly ? (DMA_UPDATE_VASPACE_FLAGS_READ_ONLY |
1825             DMA_UPDATE_VASPACE_FLAGS_SHADER_READ_ONLY) : DMA_UPDATE_VASPACE_FLAGS_NONE;
1826 
1827         if (pGVAS->flags & VASPACE_FLAGS_RESTRICTED_RM_INTERNAL_VALIMITS)
1828         {
1829             allocFlags |= DMA_ALLOC_VASPACE_USE_RM_INTERNAL_VALIMITS;
1830         }
1831 
1832         if (kgraphicsIsPerSubcontextContextHeaderSupported(pGpu, pKernelGraphics))
1833         {
1834             status = dmaMapBuffer_HAL(pGpu, GPU_GET_DMA(pGpu), pVAS, pMemDesc, &vaddr,
1835                 allocFlags, updateFlags);
1836         }
1837         else
1838         {
1839             //
1840             // Per subcontext headers not enabled.
1841             // If subcontext is not supported, create a new mapping.
1842             // If subcontext is supported, create an identity mapping to the existing one.
1843             //
1844 
1845             if (vaListMapCount(pVaList) == 0)
1846             {
1847                 status = dmaMapBuffer_HAL(pGpu, GPU_GET_DMA(pGpu), pVAS,
1848                                           pMemDesc,
1849                                           &vaddr,
1850                                           allocFlags,
1851                                           updateFlags);
1852             }
1853             else
1854             {
1855                 OBJVASPACE *pVas;
1856                 NvU32 mapFlags = 0x0;
1857                 NvU64 vaddrCached;
1858 
1859                 FOR_EACH_IN_VADDR_LIST(pVaList, pVas, vaddr)
1860                 {
1861                     // Find the first virtual address in any VAS
1862                     break;
1863                 }
1864                 FOR_EACH_IN_VADDR_LIST_END(pVaList, pVas, vaddr);
1865 
1866                 if (bIsReadOnly)
1867                 {
1868                     mapFlags = FLD_SET_DRF(OS46, _FLAGS, _ACCESS, _READ_ONLY, mapFlags);
1869                     mapFlags = FLD_SET_DRF(OS46, _FLAGS, _SHADER_ACCESS, _READ_ONLY, mapFlags);
1870                 }
1871                 mapFlags = FLD_SET_DRF(OS46, _FLAGS, _DMA_UNICAST_REUSE_ALLOC, _FALSE, mapFlags);
1872                 mapFlags = FLD_SET_DRF(OS46, _FLAGS, _DMA_OFFSET_FIXED, _TRUE, mapFlags);
1873 
1874                 NV_ASSERT(!bAlignSize); // TODO: Add support for size align
1875                 vaddrCached = vaddr;
1876                 NV_ASSERT_OK_OR_ELSE(status,
1877                     dmaAllocMapping_HAL(pGpu, GPU_GET_DMA(pGpu), pVAS, pMemDesc,
1878                                         &vaddr,
1879                                         mapFlags,
1880                                         NULL,
1881                                         KMIGMGR_SWIZZID_INVALID),
1882                     /* do nothing on error, but make sure we overwrite status */;);
1883                 NV_ASSERT(vaddr == vaddrCached);
1884             }
1885         }
1886 
1887         NV_PRINTF(LEVEL_INFO, "New ctx buffer mapping at VA 0x%llx\n", vaddr);
1888     }
1889 
1890     if (status == NV_OK)
1891         NV_ASSERT_OK_OR_RETURN(vaListAddVa(pVaList, pVAS, vaddr));
1892 
1893     return status;
1894 }
1895 
1896 /*!
1897  * @brief Unmap a GR ctx buffer
1898  */
1899 void
kgraphicsUnmapCtxBuffer_IMPL(OBJGPU * pGpu,KernelGraphics * pKernelGraphics,OBJVASPACE * pVAS,VA_LIST * pVaList)1900 kgraphicsUnmapCtxBuffer_IMPL
1901 (
1902     OBJGPU *pGpu,
1903     KernelGraphics *pKernelGraphics,
1904     OBJVASPACE *pVAS,
1905     VA_LIST *pVaList
1906 )
1907 {
1908     NV_STATUS status = NV_OK;
1909     NvU64     vaddr = 0;
1910 
1911     NV_ASSERT(!gpumgrGetBcEnabledStatus(pGpu));
1912 
1913     NV_PRINTF(LEVEL_INFO, "gpu:%d isBC=%d\n", pGpu->gpuInstance,
1914               gpumgrGetBcEnabledStatus(pGpu));
1915 
1916     status = vaListFindVa(pVaList, pVAS, &vaddr);
1917     if (status == NV_OK)
1918     {
1919         NV_ASSERT_OK(vaListRemoveVa(pVaList, pVAS));
1920 
1921         status = vaListFindVa(pVaList, pVAS, &vaddr);
1922 
1923         NV_ASSERT((NV_OK == status) || (NV_ERR_OBJECT_NOT_FOUND == status));
1924         if (NV_ERR_OBJECT_NOT_FOUND == status)
1925         {
1926             if (vaListGetManaged(pVaList))
1927             {
1928                 dmaUnmapBuffer_HAL(pGpu, GPU_GET_DMA(pGpu), pVAS, vaddr);
1929             }
1930 
1931             NV_PRINTF(LEVEL_INFO, "Freed ctx buffer mapping at VA 0x%llx\n",
1932                       vaddr);
1933         }
1934     }
1935 }
1936 
1937 /*!
1938  * @brief Get the Class number for a given gr object type
1939  *
1940  * @param[in]   pGpu
1941  * @param[in]   pKernelGraphics
1942  * @param[in]   wantObjectType   GR object type to lookup
1943  * @param[out]  pClass           class number
1944  */
1945 NV_STATUS
kgraphicsGetClassByType_IMPL(OBJGPU * pGpu,KernelGraphics * pKernelGraphics,NvU32 wantObjectType,NvU32 * pClass)1946 kgraphicsGetClassByType_IMPL
1947 (
1948     OBJGPU *pGpu,
1949     KernelGraphics *pKernelGraphics,
1950     NvU32 wantObjectType,
1951     NvU32 *pClass
1952 )
1953 {
1954     NV_STATUS status = NV_OK;
1955     NvU32 objectType;
1956     NvU32 i;
1957     NvU32 numClasses;
1958     NvU32 *pClassesSupported;
1959 
1960     *pClass = 0;
1961 
1962     if (wantObjectType >= GR_OBJECT_TYPE_INVALID)
1963     {
1964         NV_PRINTF(LEVEL_ERROR, "bad requested object type : %d\n",
1965                   wantObjectType);
1966         return NV_ERR_INVALID_ARGUMENT;
1967     }
1968 
1969     // find out how many classes of type ENG_GR(0) we have
1970     NV_ASSERT_OK_OR_RETURN(
1971         gpuGetClassList(pGpu, &numClasses, NULL, ENG_GR(pKernelGraphics->instance)));
1972 
1973     pClassesSupported = portMemAllocNonPaged(sizeof(NvU32) * numClasses);
1974     NV_CHECK_OR_RETURN(LEVEL_ERROR, pClassesSupported != NULL, NV_ERR_NO_MEMORY);
1975 
1976     status = gpuGetClassList(pGpu, &numClasses, pClassesSupported, ENG_GR(pKernelGraphics->instance));
1977 
1978     if (status == NV_OK)
1979     {
1980         for (i = 0; i < numClasses; i++)
1981         {
1982             kgrmgrGetGrObjectType(pClassesSupported[i], &objectType);
1983 
1984             NV_PRINTF(LEVEL_INFO, "classNum=0x%08x, type=%d\n",
1985                       pClassesSupported[i], objectType);
1986 
1987             if (objectType == wantObjectType)
1988                 *pClass = pClassesSupported[i];
1989         }
1990     }
1991 
1992     portMemFree(pClassesSupported);
1993 
1994     return (*pClass != 0) ? NV_OK : NV_ERR_INVALID_CLASS;
1995 }
1996 
1997 /*!
1998  * @brief retrieve the ctx attributes for the given buffer
1999  */
2000 const GR_BUFFER_ATTR *
kgraphicsGetContextBufferAttr_IMPL(OBJGPU * pGpu,KernelGraphics * pKernelGraphics,GR_CTX_BUFFER buf)2001 kgraphicsGetContextBufferAttr_IMPL
2002 (
2003     OBJGPU *pGpu,
2004     KernelGraphics *pKernelGraphics,
2005     GR_CTX_BUFFER buf
2006 )
2007 {
2008     NV_ASSERT_OR_RETURN(NV_ENUM_IS(GR_CTX_BUFFER, buf), NULL);
2009     return &pKernelGraphics->ctxAttr[buf];
2010 }
2011 
2012 /*!
2013  * @brief Creates a VEID0 channel for Golden Image creation
2014  *
2015  * @return NV_OK if channel and golden image created successfully
2016  */
2017 NV_STATUS
kgraphicsCreateGoldenImageChannel_IMPL(OBJGPU * pGpu,KernelGraphics * pKernelGraphics)2018 kgraphicsCreateGoldenImageChannel_IMPL
2019 (
2020     OBJGPU *pGpu,
2021     KernelGraphics *pKernelGraphics
2022 )
2023 {
2024     NV_STATUS                              status = NV_OK;
2025     NvHandle                               hClientId = NV01_NULL_OBJECT;
2026     NvHandle                               hDeviceId;
2027     NvHandle                               hSubdeviceId;
2028     NvHandle                               hVASpace = 0xbaba0042;
2029     NvHandle                               hPBVirtMemId = 0xbaba0043;
2030     NvHandle                               hPBPhysMemId = 0xbaba0044;
2031     NvHandle                               hChannelId = 0xbaba0045;
2032     NvHandle                               hObj3D = 0xbaba0046;
2033     NvHandle                               hUserdId = 0xbaba0049;
2034     NvU32                                  gpFifoEntries = 32;       // power-of-2 random choice
2035     NvU64                                  gpFifoSize = NVA06F_GP_ENTRY__SIZE * gpFifoEntries;
2036     NvU64                                  chSize = gpFifoSize;
2037     RM_API                                *pRmApi = rmapiGetInterface(RMAPI_GPU_LOCK_INTERNAL);
2038     RsClient                              *pClientId;
2039     KernelMIGManager                      *pKernelMIGManager = GPU_GET_KERNEL_MIG_MANAGER(pGpu);
2040     NvBool                                 bNeedMIGWar;
2041     NvBool                                 bBcStatus;
2042     NvBool                                 bClientUserd = IsVOLTAorBetter(pGpu);
2043     NvBool                                 bAcquireLock = NV_FALSE;
2044     NvU32                                  sliLoopReentrancy;
2045     NV_VASPACE_ALLOCATION_PARAMETERS       vaParams;
2046     NV_MEMORY_ALLOCATION_PARAMS            memAllocParams;
2047     NV_CHANNEL_ALLOC_PARAMS channelGPFIFOAllocParams;
2048     NvU32                                  classNum;
2049     MIG_INSTANCE_REF                       ref;
2050     NvU32                                  objectType;
2051     NvU32                                  primarySliSubDeviceInstance;
2052 
2053     // XXX This should be removed when broadcast SLI support is deprecated
2054     if (!gpumgrIsParentGPU(pGpu))
2055     {
2056         return NV_OK;
2057     }
2058 
2059     bBcStatus = gpumgrGetBcEnabledStatus(pGpu);
2060 
2061     // FIXME these allocations corrupt BC state
2062     NV_ASSERT_OK_OR_RETURN(
2063         rmapiutilAllocClientAndDeviceHandles(pRmApi, pGpu, &hClientId, &hDeviceId, &hSubdeviceId));
2064     // rmapiutilAllocClientAndDeviceHandles allocates a subdevice object for this subDeviceInstance
2065     primarySliSubDeviceInstance = gpumgrGetSubDeviceInstanceFromGpu(pGpu);
2066 
2067     NV_ASSERT_OK_OR_RETURN(serverGetClientUnderLock(&g_resServ, hClientId, &pClientId));
2068 
2069     gpumgrSetBcEnabledStatus(pGpu, NV_TRUE);
2070 
2071     // As we have forced here SLI broadcast mode, temporarily reset the reentrancy count
2072     sliLoopReentrancy = gpumgrSLILoopReentrancyPop(pGpu);
2073 
2074     bNeedMIGWar = IS_MIG_IN_USE(pGpu);
2075 
2076     // Allocate subdevices for secondary GPUs
2077     SLI_LOOP_START(SLI_LOOP_FLAGS_BC_ONLY)
2078     {
2079         NvHandle hSecondary;
2080         NV2080_ALLOC_PARAMETERS nv2080AllocParams;
2081         NvU32 thisSubDeviceInstance = gpumgrGetSubDeviceInstanceFromGpu(pGpu);
2082 
2083         // Skip if already allocated by rmapiutilAllocClientAndDeviceHandles()
2084         if (thisSubDeviceInstance == primarySliSubDeviceInstance)
2085             SLI_LOOP_CONTINUE;
2086 
2087         // Allocate a subDevice
2088         NV_CHECK_OK_OR_GOTO(status, LEVEL_ERROR,
2089             clientGenResourceHandle(pClientId, &hSecondary),
2090             cleanup);
2091 
2092         portMemSet(&nv2080AllocParams, 0, sizeof(nv2080AllocParams));
2093         nv2080AllocParams.subDeviceId = thisSubDeviceInstance;
2094 
2095         NV_CHECK_OK(status, LEVEL_SILENT,
2096             pRmApi->AllocWithHandle(pRmApi,
2097                                     hClientId,
2098                                     hDeviceId,
2099                                     hSecondary,
2100                                     NV20_SUBDEVICE_0,
2101                                     &nv2080AllocParams,
2102                                     sizeof(nv2080AllocParams)));
2103     }
2104     SLI_LOOP_END;
2105 
2106     if (bNeedMIGWar)
2107     {
2108         NvHandle hPartitionRef = 0xbaba0048;
2109         NvHandle hExecPartitionRef = 0xbaba004a;
2110         NVC637_ALLOCATION_PARAMETERS nvC637AllocParams = {0};
2111 
2112         // Get swizzId for this GR
2113         NV_ASSERT_OK_OR_GOTO(status,
2114             kmigmgrGetMIGReferenceFromEngineType(pGpu, pKernelMIGManager,
2115                                                  RM_ENGINE_TYPE_GR(pKernelGraphics->instance), &ref),
2116             cleanup);
2117 
2118         portMemSet(&nvC637AllocParams, 0, sizeof(NVC637_ALLOCATION_PARAMETERS));
2119         nvC637AllocParams.swizzId = ref.pKernelMIGGpuInstance->swizzId;
2120 
2121         // allocate partition reference
2122         NV_ASSERT_OK_OR_GOTO(status,
2123             pRmApi->AllocWithHandle(pRmApi,
2124                                     hClientId,
2125                                     hSubdeviceId,
2126                                     hPartitionRef,
2127                                     AMPERE_SMC_PARTITION_REF,
2128                                     &nvC637AllocParams,
2129                                     sizeof(nvC637AllocParams)),
2130             cleanup);
2131 
2132         if (ref.pMIGComputeInstance != NULL)
2133         {
2134             NVC638_ALLOCATION_PARAMETERS nvC638AllocParams = {0};
2135             nvC638AllocParams.execPartitionId = ref.pMIGComputeInstance->id;
2136             NV_ASSERT_OK_OR_GOTO(status,
2137                 pRmApi->AllocWithHandle(pRmApi,
2138                                         hClientId,
2139                                         hPartitionRef,
2140                                         hExecPartitionRef,
2141                                         AMPERE_SMC_EXEC_PARTITION_REF,
2142                                         &nvC638AllocParams,
2143                                         sizeof(nvC638AllocParams)),
2144                 cleanup);
2145         }
2146     }
2147 
2148     //
2149     // VidHeapControl and vaspace creation calls should happen outside GPU locks
2150     // UVM/CUDA may be holding the GPU locks here and the allocation may subsequently fail
2151     // So explicitly release GPU locks before RmVidHeapControl
2152     // See Bug 1735851-#24
2153     //
2154     rmGpuLocksRelease(GPUS_LOCK_FLAGS_NONE, NULL);
2155     bAcquireLock = NV_TRUE;
2156     pRmApi = rmapiGetInterface(RMAPI_API_LOCK_INTERNAL);
2157 
2158     // Create a new VAspace for channel
2159     portMemSet(&vaParams, 0, sizeof(NV_VASPACE_ALLOCATION_PARAMETERS));
2160     NV_ASSERT_OK_OR_GOTO(status,
2161         pRmApi->AllocWithHandle(pRmApi, hClientId, hDeviceId, hVASpace, FERMI_VASPACE_A, &vaParams, sizeof(vaParams)),
2162         cleanup);
2163 
2164     // Allocate gpfifo entries
2165     portMemSet(&memAllocParams, 0, sizeof(NV_MEMORY_ALLOCATION_PARAMS));
2166     memAllocParams.owner     = HEAP_OWNER_RM_CLIENT_GENERIC;
2167     memAllocParams.type      = NVOS32_TYPE_IMAGE;
2168     memAllocParams.size      = chSize;
2169     memAllocParams.attr      = DRF_DEF(OS32, _ATTR, _LOCATION, _PCI);
2170     memAllocParams.hVASpace  = 0; // Physical allocations don't expect vaSpace handles
2171 
2172     //
2173     // When APM feature is enabled all RM internal sysmem allocations must
2174     // be in unprotected memory
2175     // When Hopper CC is enabled all RM internal sysmem allocations that
2176     // are required to be accessed from GPU should be in unprotected memory
2177     // Other sysmem allocations that are not required to be accessed from GPU
2178     // must be in protected memory
2179     //
2180     memAllocParams.attr2 |= DRF_DEF(OS32, _ATTR2, _MEMORY_PROTECTION, _UNPROTECTED);
2181 
2182     NV_ASSERT_OK_OR_GOTO(status,
2183         pRmApi->AllocWithHandle(pRmApi, hClientId, hDeviceId, hPBPhysMemId, NV01_MEMORY_SYSTEM, &memAllocParams, sizeof(memAllocParams)),
2184         cleanup);
2185 
2186     portMemSet(&memAllocParams, 0, sizeof(NV_MEMORY_ALLOCATION_PARAMS));
2187     memAllocParams.owner     = HEAP_OWNER_RM_CLIENT_GENERIC;
2188     memAllocParams.type      = NVOS32_TYPE_IMAGE;
2189     memAllocParams.size      = chSize;
2190     memAllocParams.attr      = DRF_DEF(OS32, _ATTR, _LOCATION, _PCI);
2191     memAllocParams.flags     = NVOS32_ALLOC_FLAGS_VIRTUAL;
2192     memAllocParams.hVASpace  = hVASpace; // Virtual allocation expect vaSpace handles
2193                                          // 0 handle = allocations on gpu default vaSpace
2194 
2195     NV_ASSERT_OK_OR_GOTO(status,
2196         pRmApi->AllocWithHandle(pRmApi, hClientId, hDeviceId, hPBVirtMemId, NV50_MEMORY_VIRTUAL, &memAllocParams, sizeof(memAllocParams)),
2197         cleanup);
2198 
2199     // Allocate Userd
2200     if (bClientUserd)
2201     {
2202         NvU32 userdMemClass = NV01_MEMORY_LOCAL_USER;
2203         NvU32 ctrlSize;
2204 
2205         if (gpuIsClassSupported(pGpu, VOLTA_CHANNEL_GPFIFO_A))
2206         {
2207             ctrlSize = sizeof(Nvc36fControl);
2208         }
2209         else if (gpuIsClassSupported(pGpu, TURING_CHANNEL_GPFIFO_A))
2210         {
2211             ctrlSize = sizeof(Nvc46fControl);
2212         }
2213         else if (gpuIsClassSupported(pGpu, AMPERE_CHANNEL_GPFIFO_A))
2214         {
2215             ctrlSize = sizeof(Nvc56fControl);
2216         }
2217         else if (gpuIsClassSupported(pGpu, HOPPER_CHANNEL_GPFIFO_A))
2218         {
2219             ctrlSize = sizeof(Nvc86fControl);
2220         }
2221         else
2222         {
2223             status = NV_ERR_NOT_SUPPORTED;
2224             goto cleanup;
2225         }
2226 
2227         portMemSet(&memAllocParams, 0, sizeof(NV_MEMORY_ALLOCATION_PARAMS));
2228         memAllocParams.owner = HEAP_OWNER_RM_CLIENT_GENERIC;
2229         memAllocParams.size  = ctrlSize;
2230         memAllocParams.type  = NVOS32_TYPE_IMAGE;
2231 
2232         // Apply registry overrides to USERD.
2233         switch (DRF_VAL(_REG_STR_RM, _INST_LOC, _USERD, pGpu->instLocOverrides))
2234         {
2235             case NV_REG_STR_RM_INST_LOC_USERD_NCOH:
2236             case NV_REG_STR_RM_INST_LOC_USERD_COH:
2237                 userdMemClass = NV01_MEMORY_SYSTEM;
2238                 memAllocParams.attr = DRF_DEF(OS32, _ATTR, _LOCATION, _PCI);
2239                 break;
2240 
2241             case NV_REG_STR_RM_INST_LOC_USERD_VID:
2242             case NV_REG_STR_RM_INST_LOC_USERD_DEFAULT:
2243                 memAllocParams.attr = DRF_DEF(OS32, _ATTR, _LOCATION, _VIDMEM);
2244                 break;
2245         }
2246 
2247         //
2248         // When APM is enabled all RM internal allocations must to go to
2249         // unprotected memory irrespective of vidmem or sysmem
2250         // When Hopper CC is enabled all RM internal sysmem allocations that
2251         // are required to be accessed from GPU should be in unprotected memory
2252         // and all vidmem allocations must go to protected memory
2253         //
2254         if (gpuIsApmFeatureEnabled(pGpu) ||
2255             FLD_TEST_DRF(OS32, _ATTR, _LOCATION, _PCI, memAllocParams.attr))
2256         {
2257             memAllocParams.attr2 |= DRF_DEF(OS32, _ATTR2, _MEMORY_PROTECTION,
2258                                             _UNPROTECTED);
2259         }
2260 
2261         NV_ASSERT_OK_OR_GOTO(status,
2262             pRmApi->AllocWithHandle(pRmApi, hClientId, hDeviceId, hUserdId,
2263                                     userdMemClass, &memAllocParams, sizeof(memAllocParams)),
2264             cleanup);
2265     }
2266 
2267     // Get fifo channel class Id
2268     classNum = kfifoGetChannelClassId(pGpu, GPU_GET_KERNEL_FIFO(pGpu));
2269     NV_ASSERT_OR_GOTO(classNum != 0, cleanup);
2270 
2271     // Allocate a bare channel
2272     portMemSet(&channelGPFIFOAllocParams, 0, sizeof(NV_CHANNEL_ALLOC_PARAMS));
2273     channelGPFIFOAllocParams.hVASpace      = hVASpace;
2274     channelGPFIFOAllocParams.hObjectBuffer = hPBVirtMemId;
2275     channelGPFIFOAllocParams.gpFifoEntries = gpFifoEntries;
2276     //
2277     // Set the gpFifoOffset to zero intentionally since we only need this channel
2278     // to be created, but will not submit any work to it. So it's fine not to
2279     // provide a valid offset here.
2280     //
2281     channelGPFIFOAllocParams.gpFifoOffset  = 0;
2282     if (bClientUserd)
2283     {
2284         channelGPFIFOAllocParams.hUserdMemory[0] = hUserdId;
2285     }
2286 
2287     if (bNeedMIGWar)
2288     {
2289         RM_ENGINE_TYPE localRmEngineType;
2290         Device *pDevice;
2291 
2292         NV_ASSERT_OK_OR_GOTO(status,
2293             deviceGetByHandle(pClientId, hDeviceId, &pDevice),
2294             cleanup);
2295 
2296         NV_ASSERT_OK_OR_GOTO(status,
2297             kmigmgrGetInstanceRefFromDevice(pGpu, pKernelMIGManager, pDevice, &ref),
2298             cleanup);
2299 
2300         NV_ASSERT_OK_OR_GOTO(status,
2301             kmigmgrGetGlobalToLocalEngineType(pGpu, pKernelMIGManager, ref, RM_ENGINE_TYPE_GR(pKernelGraphics->instance), &localRmEngineType),
2302             cleanup);
2303 
2304         channelGPFIFOAllocParams.engineType = gpuGetNv2080EngineType(localRmEngineType);
2305     }
2306     else
2307     {
2308         channelGPFIFOAllocParams.engineType = gpuGetNv2080EngineType(RM_ENGINE_TYPE_GR0);
2309     }
2310 
2311     NV_ASSERT_OK_OR_GOTO(status,
2312         pRmApi->AllocWithHandle(pRmApi, hClientId, hDeviceId, hChannelId,
2313                                 classNum, &channelGPFIFOAllocParams, sizeof(channelGPFIFOAllocParams)),
2314         cleanup);
2315 
2316     //
2317     // When using split VAS, we need to reserve enough pagepool memory to
2318     // sustain large context buffer mappings. For GSPCLIENT where the golden
2319     // context buffer channel is initialized on boot, the pagepool does not have
2320     // enough reserved memory to accommodate these buffers, so we need to
2321     // reserve extra here.
2322     //
2323     if (IS_GSP_CLIENT(pGpu))
2324     {
2325         KernelChannel *pKernelChannel;
2326         NvU64 reserveSize;
2327         const KGRAPHICS_STATIC_INFO *pKernelGraphicsStaticInfo = kgraphicsGetStaticInfo(pGpu, pKernelGraphics);
2328         NvU32 i;
2329 
2330         NV_ASSERT_OK(CliGetKernelChannel(pClientId, hChannelId, &pKernelChannel));
2331 
2332         NV_ASSERT_OR_ELSE(pKernelGraphicsStaticInfo != NULL,
2333             status = NV_ERR_INVALID_STATE;
2334             goto cleanup;);
2335         NV_ASSERT_OR_ELSE(pKernelGraphicsStaticInfo->pContextBuffersInfo != NULL,
2336             status = NV_ERR_INVALID_STATE;
2337             goto cleanup;);
2338 
2339         reserveSize = 0;
2340         for (i = 0; i < NV_ARRAY_ELEMENTS(pKernelGraphicsStaticInfo->pContextBuffersInfo->engine); ++i)
2341         {
2342             if (pKernelGraphicsStaticInfo->pContextBuffersInfo->engine[i].size != NV_U32_MAX)
2343                 reserveSize += pKernelGraphicsStaticInfo->pContextBuffersInfo->engine[i].size;
2344         }
2345 
2346         NV_ASSERT_OK(
2347             vaspaceReserveMempool(pKernelChannel->pVAS, pGpu,
2348                                   GPU_RES_GET_DEVICE(pKernelChannel),
2349                                   reserveSize, RM_PAGE_SIZE,
2350                                   VASPACE_RESERVE_FLAGS_NONE));
2351     }
2352 
2353     // Reaquire the GPU locks
2354     NV_ASSERT_OK_OR_GOTO(status,
2355         rmGpuLocksAcquire(GPUS_LOCK_FLAGS_NONE, RM_LOCK_MODULES_GR),
2356         cleanup);
2357     bAcquireLock = NV_FALSE;
2358     pRmApi = rmapiGetInterface(RMAPI_GPU_LOCK_INTERNAL);
2359 
2360     if (!bNeedMIGWar)
2361     {
2362         objectType = GR_OBJECT_TYPE_3D;
2363     }
2364     else
2365     {
2366         objectType = GR_OBJECT_TYPE_COMPUTE;
2367 
2368     }
2369 
2370     // Get KernelGraphicsObject class Id
2371     NV_ASSERT_OK_OR_GOTO(status,
2372         kgraphicsGetClassByType(pGpu, pKernelGraphics, objectType, &classNum),
2373         cleanup);
2374     NV_ASSERT_OR_GOTO(classNum != 0, cleanup);
2375 
2376     // Allocate a GR object on the channel
2377     NV_ASSERT_OK_OR_GOTO(status,
2378         pRmApi->AllocWithHandle(pRmApi, hClientId, hChannelId, hObj3D, classNum, NULL, 0),
2379         cleanup);
2380 
2381 cleanup:
2382 
2383     if (bAcquireLock)
2384     {
2385         NV_ASSERT_OK_OR_CAPTURE_FIRST_ERROR(status,
2386             rmGpuLocksAcquire(GPUS_LOCK_FLAGS_NONE, RM_LOCK_MODULES_GR));
2387     }
2388 
2389     // Free all handles
2390     NV_ASSERT_OK_OR_CAPTURE_FIRST_ERROR(status,
2391         pRmApi->Free(pRmApi, hClientId, hClientId));
2392 
2393     // Restore the reentrancy count
2394     gpumgrSLILoopReentrancyPush(pGpu, sliLoopReentrancy);
2395 
2396     gpumgrSetBcEnabledStatus(pGpu, bBcStatus);
2397 
2398     return status;
2399 }
2400 
2401 /*!
2402  * @brief Free context buffers shared by all/most graphics contexts
2403  */
kgraphicsFreeGlobalCtxBuffers_IMPL(OBJGPU * pGpu,KernelGraphics * pKernelGraphics,NvU32 gfid)2404 void kgraphicsFreeGlobalCtxBuffers_IMPL
2405 (
2406     OBJGPU *pGpu,
2407     KernelGraphics *pKernelGraphics,
2408     NvU32 gfid
2409 )
2410 {
2411     KernelMemorySystem *pKernelMemorySystem = GPU_GET_KERNEL_MEMORY_SYSTEM(pGpu);
2412     GR_GLOBALCTX_BUFFERS *pCtxBuffers;
2413     GR_GLOBALCTX_BUFFER buff;
2414     NvBool bEvict = NV_FALSE;
2415 
2416     NV_ASSERT(!gpumgrGetBcEnabledStatus(pGpu));
2417 
2418     if (pKernelGraphics->globalCtxBuffersInfo.pGlobalCtxBuffers == NULL)
2419         return;
2420 
2421     pCtxBuffers = &pKernelGraphics->globalCtxBuffersInfo.pGlobalCtxBuffers[gfid];
2422 
2423     if (!pCtxBuffers->bAllocated)
2424         return;
2425 
2426     FOR_EACH_IN_ENUM(GR_GLOBALCTX_BUFFER, buff)
2427     {
2428         if (pCtxBuffers->memDesc[buff] != NULL)
2429         {
2430             bEvict = NV_TRUE;
2431 
2432             memdescFree(pCtxBuffers->memDesc[buff]);
2433             memdescDestroy(pCtxBuffers->memDesc[buff]);
2434             pCtxBuffers->memDesc[buff] = NULL;
2435             pCtxBuffers->bInitialized[buff] = NV_FALSE;
2436         }
2437     }
2438     FOR_EACH_IN_ENUM_END;
2439 
2440     pCtxBuffers->bAllocated = NV_FALSE;
2441 
2442     // make sure all L2 cache lines using CB buffers are clear after we free them
2443     if (bEvict)
2444         NV_ASSERT_OK(kmemsysCacheOp_HAL(pGpu, pKernelMemorySystem, NULL, FB_CACHE_VIDEO_MEMORY, FB_CACHE_EVICT));
2445 }
2446 
2447 NV_STATUS
kgraphicsGetCaps_IMPL(OBJGPU * pGpu,KernelGraphics * pKernelGraphics,NvU8 * pGrCaps)2448 kgraphicsGetCaps_IMPL
2449 (
2450     OBJGPU *pGpu,
2451     KernelGraphics *pKernelGraphics,
2452     NvU8 *pGrCaps
2453 )
2454 {
2455     const KGRAPHICS_STATIC_INFO *pKernelGraphicsStaticInfo = kgraphicsGetStaticInfo(pGpu, pKernelGraphics);
2456 
2457     NV_ASSERT_OR_RETURN(pGrCaps != NULL, NV_ERR_INVALID_ARGUMENT);
2458     NV_ASSERT_OR_RETURN(pKernelGraphicsStaticInfo != NULL, NV_ERR_INVALID_STATE);
2459 
2460     portMemCopy(pGrCaps,
2461                 NV0080_CTRL_GR_CAPS_TBL_SIZE * sizeof(*pGrCaps),
2462                 pKernelGraphicsStaticInfo->grCaps.capsTbl,
2463                 NV0080_CTRL_GR_CAPS_TBL_SIZE * sizeof(*pGrCaps));
2464 
2465     return NV_OK;
2466 }
2467 
2468 /*!
2469  * @brief Return whether unrestricted register access bufffer is supported or not.
2470  */
2471 NvBool
kgraphicsIsUnrestrictedAccessMapSupported_PF(OBJGPU * pGpu,KernelGraphics * pKernelGraphics)2472 kgraphicsIsUnrestrictedAccessMapSupported_PF
2473 (
2474     OBJGPU *pGpu,
2475     KernelGraphics *pKernelGraphics
2476 )
2477 {
2478     return !hypervisorIsVgxHyper();
2479 }
2480 
2481 /*!
2482  * @brief Provides an opportunity to register some IntrService during intrStateInit.
2483  */
2484 void
kgraphicsRegisterIntrService_IMPL(OBJGPU * pGpu,KernelGraphics * pKernelGraphics,IntrServiceRecord pRecords[MC_ENGINE_IDX_MAX])2485 kgraphicsRegisterIntrService_IMPL
2486 (
2487     OBJGPU *pGpu,
2488     KernelGraphics *pKernelGraphics,
2489     IntrServiceRecord pRecords[MC_ENGINE_IDX_MAX]
2490 )
2491 {
2492     NvU32 engineIdx = MC_ENGINE_IDX_GRn_FECS_LOG(pKernelGraphics->instance);
2493 
2494     NV_ASSERT(pRecords[engineIdx].pInterruptService == NULL);
2495     pRecords[engineIdx].pInterruptService = staticCast(pKernelGraphics, IntrService);
2496 
2497     engineIdx = MC_ENGINE_IDX_GRn(pKernelGraphics->instance);
2498 
2499     NV_ASSERT(pRecords[engineIdx].pNotificationService == NULL);
2500     pRecords[engineIdx].bFifoWaiveNotify = NV_FALSE;
2501     pRecords[engineIdx].pNotificationService = staticCast(pKernelGraphics, IntrService);
2502 }
2503 
2504 /*!
2505  * @brief Services the nonstall interrupt.
2506  */
2507 NvU32
kgraphicsServiceNotificationInterrupt_IMPL(OBJGPU * pGpu,KernelGraphics * pKernelGraphics,IntrServiceServiceNotificationInterruptArguments * pParams)2508 kgraphicsServiceNotificationInterrupt_IMPL
2509 (
2510     OBJGPU *pGpu,
2511     KernelGraphics *pKernelGraphics,
2512     IntrServiceServiceNotificationInterruptArguments *pParams
2513 )
2514 {
2515     NvU32 grIdx = pKernelGraphics->instance;
2516 
2517     NV_ASSERT_OR_RETURN(pParams != NULL, 0);
2518     NV_ASSERT_OR_RETURN(pParams->engineIdx == MC_ENGINE_IDX_GRn(grIdx), 0);
2519 
2520     MODS_ARCH_REPORT(NV_ARCH_EVENT_NONSTALL_GR, "%s", "processing GR nonstall interrupt\n");
2521 
2522     kgraphicsNonstallIntrCheckAndClear_HAL(pGpu, pKernelGraphics, pParams->pThreadState);
2523     engineNonStallIntrNotify(pGpu, RM_ENGINE_TYPE_GR(pKernelGraphics->instance));
2524     return NV_OK;
2525 }
2526 
2527 /*!
2528  * KernelGraphics RM Device Controls
2529  */
2530 
2531 /*!
2532  * deviceCtrlCmdKGrGetCaps_IMPL
2533  *
2534  * Lock Requirements:
2535  *      Assert that API lock held on entry
2536  *
2537  * TODO: remove once all uses have been migrated to V2
2538  */
2539 NV_STATUS
deviceCtrlCmdKGrGetCaps_IMPL(Device * pDevice,NV0080_CTRL_GR_GET_CAPS_PARAMS * pParams)2540 deviceCtrlCmdKGrGetCaps_IMPL
2541 (
2542     Device *pDevice,
2543     NV0080_CTRL_GR_GET_CAPS_PARAMS *pParams
2544 )
2545 {
2546     OBJGPU *pGpu = GPU_RES_GET_GPU(pDevice);
2547     NvU8 *pGrCaps = NvP64_VALUE(pParams->capsTbl);
2548     NvBool bCapsPopulated = NV_FALSE;
2549 
2550     LOCK_ASSERT_AND_RETURN(rmapiLockIsOwner());
2551 
2552     if (IsDFPGA(pGpu))
2553     {
2554         return NV_ERR_NOT_SUPPORTED;
2555     }
2556 
2557     NV_CHECK_OR_RETURN(LEVEL_ERROR, pGrCaps != NULL, NV_ERR_INVALID_ARGUMENT);
2558     NV_CHECK_OR_RETURN(LEVEL_ERROR, pParams->capsTblSize == NV0080_CTRL_GR_CAPS_TBL_SIZE, NV_ERR_INVALID_ARGUMENT);
2559 
2560     SLI_LOOP_START(SLI_LOOP_FLAGS_BC_ONLY)
2561     {
2562         KernelGraphicsManager *pKernelGraphicsManager = GPU_GET_KERNEL_GRAPHICS_MANAGER(pGpu);
2563         KernelGraphics *pKernelGraphics;
2564         NV2080_CTRL_GR_ROUTE_INFO grRouteInfo;
2565         NV_STATUS status;
2566 
2567         portMemSet(&grRouteInfo, 0, sizeof(grRouteInfo));
2568         kgrmgrCtrlSetEngineID(0, &grRouteInfo);
2569         NV_CHECK_OK_OR_ELSE(status, LEVEL_ERROR,
2570             kgrmgrCtrlRouteKGRWithDevice(pGpu, pKernelGraphicsManager, pDevice, &grRouteInfo, &pKernelGraphics),
2571             SLI_LOOP_RETURN(status););
2572 
2573         if (!bCapsPopulated)
2574         {
2575             NV_CHECK_OK_OR_ELSE(status, LEVEL_ERROR,
2576                 kgraphicsGetCaps(pGpu, pKernelGraphics, pGrCaps),
2577                 SLI_LOOP_RETURN(status););
2578 
2579             bCapsPopulated = NV_TRUE;
2580         }
2581     }
2582     SLI_LOOP_END
2583 
2584     return NV_OK;
2585 }
2586 
2587 /*!
2588  * deviceCtrlCmdKGrGetCapsV2_IMPL
2589  *
2590  * Lock Requirements:
2591  *      Assert that API lock held on entry
2592  */
2593 NV_STATUS
deviceCtrlCmdKGrGetCapsV2_IMPL(Device * pDevice,NV0080_CTRL_GR_GET_CAPS_V2_PARAMS * pParams)2594 deviceCtrlCmdKGrGetCapsV2_IMPL
2595 (
2596     Device *pDevice,
2597     NV0080_CTRL_GR_GET_CAPS_V2_PARAMS *pParams
2598 )
2599 {
2600     OBJGPU *pGpu = GPU_RES_GET_GPU(pDevice);
2601 
2602     LOCK_ASSERT_AND_RETURN(rmapiLockIsOwner());
2603 
2604     if (IsDFPGA(pGpu))
2605     {
2606         return NV_ERR_NOT_SUPPORTED;
2607     }
2608 
2609     SLI_LOOP_START(SLI_LOOP_FLAGS_BC_ONLY)
2610     {
2611         KernelGraphicsManager *pKernelGraphicsManager = GPU_GET_KERNEL_GRAPHICS_MANAGER(pGpu);
2612         KernelGraphics *pKernelGraphics;
2613         NV2080_CTRL_GR_ROUTE_INFO grRouteInfo = pParams->grRouteInfo;
2614         NV_STATUS status;
2615 
2616         kgrmgrCtrlSetEngineID(0, &grRouteInfo);
2617         NV_CHECK_OK_OR_ELSE(status, LEVEL_ERROR,
2618             kgrmgrCtrlRouteKGRWithDevice(pGpu, pKernelGraphicsManager, pDevice, &grRouteInfo, &pKernelGraphics),
2619             SLI_LOOP_RETURN(status););
2620 
2621         if (!pParams->bCapsPopulated)
2622         {
2623             NV_CHECK_OK_OR_ELSE(status, LEVEL_ERROR,
2624                 kgraphicsGetCaps(pGpu, pKernelGraphics, pParams->capsTbl),
2625                 SLI_LOOP_RETURN(status););
2626 
2627             pParams->bCapsPopulated = NV_TRUE;
2628         }
2629     }
2630     SLI_LOOP_END
2631 
2632     return NV_OK;
2633 }
2634 
2635 static NV_STATUS
_kgraphicsCtrlCmdGrGetInfoV2(OBJGPU * pGpu,Device * pDevice,NV2080_CTRL_GR_GET_INFO_V2_PARAMS * pParams)2636 _kgraphicsCtrlCmdGrGetInfoV2
2637 (
2638     OBJGPU *pGpu,
2639     Device *pDevice,
2640     NV2080_CTRL_GR_GET_INFO_V2_PARAMS *pParams
2641 )
2642 {
2643     NV_STATUS status = NV_OK;
2644     KernelGraphicsManager *pKernelGraphicsManager = GPU_GET_KERNEL_GRAPHICS_MANAGER(pGpu);
2645     NvU32 grInfoListSize = pParams->grInfoListSize;
2646     KernelMIGManager *pKernelMIGManager = GPU_GET_KERNEL_MIG_MANAGER(pGpu);
2647     NV2080_CTRL_INTERNAL_STATIC_GR_INFO *pGrInfo;
2648     NvU32 i;
2649 
2650     if (pKernelGraphicsManager == NULL)
2651     {
2652         return NV_ERR_NOT_SUPPORTED;
2653     }
2654 
2655     if ((0 == grInfoListSize) ||
2656         (grInfoListSize > NV2080_CTRL_GR_INFO_MAX_SIZE))
2657     {
2658         NV_PRINTF(LEVEL_ERROR, "Invalid grInfoList size: 0x%x\n", grInfoListSize);
2659         return NV_ERR_INVALID_ARGUMENT;
2660     }
2661 
2662     if (kmigmgrIsDeviceUsingDeviceProfiling(pGpu, pKernelMIGManager, pDevice))
2663     {
2664         NV_ASSERT_OR_RETURN(kgrmgrGetLegacyKGraphicsStaticInfo(pGpu, pKernelGraphicsManager)->bInitialized, NV_ERR_INVALID_STATE);
2665         NV_ASSERT_OR_RETURN(kgrmgrGetLegacyKGraphicsStaticInfo(pGpu, pKernelGraphicsManager)->pGrInfo != NULL, NV_ERR_NOT_SUPPORTED);
2666 
2667         pGrInfo = kgrmgrGetLegacyKGraphicsStaticInfo(pGpu, pKernelGraphicsManager)->pGrInfo;
2668     }
2669     else
2670     {
2671         KernelGraphics *pKernelGraphics;
2672         const KGRAPHICS_STATIC_INFO *pKernelGraphicsStaticInfo;
2673 
2674         NV_CHECK_OK_OR_RETURN(LEVEL_ERROR,
2675             kgrmgrCtrlRouteKGRWithDevice(pGpu, pKernelGraphicsManager, pDevice, &pParams->grRouteInfo, &pKernelGraphics));
2676 
2677         pKernelGraphicsStaticInfo = kgraphicsGetStaticInfo(pGpu, pKernelGraphics);
2678         NV_ASSERT_OR_RETURN(pKernelGraphicsStaticInfo != NULL, NV_ERR_INVALID_STATE);
2679         NV_ASSERT_OR_RETURN(pKernelGraphicsStaticInfo->pGrInfo != NULL, NV_ERR_NOT_SUPPORTED);
2680 
2681         pGrInfo = pKernelGraphicsStaticInfo->pGrInfo;
2682     }
2683 
2684     for (i = 0; i < grInfoListSize; i++)
2685     {
2686         NV_CHECK_OR_RETURN(LEVEL_ERROR, pParams->grInfoList[i].index < NV2080_CTRL_GR_INFO_MAX_SIZE, NV_ERR_INVALID_ARGUMENT);
2687         pParams->grInfoList[i].data = pGrInfo->infoList[pParams->grInfoList[i].index].data;
2688     }
2689 
2690     return status;
2691 }
2692 
2693 /*!
2694  * deviceCtrlCmdKGrGetInfo
2695  *
2696  * Lock Requirements:
2697  *      Assert that API lock and GPUs lock held on entry
2698  *
2699  * TODO: remove once all uses have been migrated to V2
2700  */
2701 NV_STATUS
deviceCtrlCmdKGrGetInfo_IMPL(Device * pDevice,NV0080_CTRL_GR_GET_INFO_PARAMS * pParams)2702 deviceCtrlCmdKGrGetInfo_IMPL
2703 (
2704     Device *pDevice,
2705     NV0080_CTRL_GR_GET_INFO_PARAMS *pParams
2706 )
2707 {
2708     OBJGPU *pGpu = GPU_RES_GET_GPU(pDevice);
2709     NV0080_CTRL_GR_GET_INFO_V2_PARAMS grInfoParamsV2;
2710     NV0080_CTRL_GR_INFO *pGrInfos = NvP64_VALUE(pParams->grInfoList);
2711     NvU32 grInfoListSize = NV_MIN(pParams->grInfoListSize,
2712                                   NV0080_CTRL_GR_INFO_MAX_SIZE);
2713 
2714     LOCK_ASSERT_AND_RETURN(rmapiLockIsOwner() && rmGpuLockIsOwner());
2715 
2716     NV_CHECK_OR_RETURN(LEVEL_ERROR, pGrInfos != NULL, NV_ERR_INVALID_ARGUMENT);
2717 
2718     portMemSet(&grInfoParamsV2, 0, sizeof(grInfoParamsV2));
2719     portMemCopy(grInfoParamsV2.grInfoList, grInfoListSize * sizeof(*pGrInfos),
2720                 pGrInfos, grInfoListSize * sizeof(*pGrInfos));
2721     grInfoParamsV2.grInfoListSize = grInfoListSize;
2722 
2723     NV_CHECK_OK_OR_RETURN(LEVEL_ERROR,
2724         _kgraphicsCtrlCmdGrGetInfoV2(pGpu, pDevice, &grInfoParamsV2));
2725 
2726     portMemCopy(pGrInfos, grInfoListSize * sizeof(*pGrInfos),
2727                 grInfoParamsV2.grInfoList, grInfoListSize * sizeof(*pGrInfos));
2728     return NV_OK;
2729 }
2730 
2731 /*!
2732  * deviceCtrlCmdKGrGetInfoV2
2733  *
2734  * Lock Requirements:
2735  *      Assert that API lock and GPUs lock held on entry
2736  */
2737 NV_STATUS
deviceCtrlCmdKGrGetInfoV2_IMPL(Device * pDevice,NV0080_CTRL_GR_GET_INFO_V2_PARAMS * pParams)2738 deviceCtrlCmdKGrGetInfoV2_IMPL
2739 (
2740     Device *pDevice,
2741     NV0080_CTRL_GR_GET_INFO_V2_PARAMS *pParams
2742 )
2743 {
2744     OBJGPU *pGpu = GPU_RES_GET_GPU(pDevice);
2745 
2746     LOCK_ASSERT_AND_RETURN(rmapiLockIsOwner() && rmGpuLockIsOwner());
2747 
2748     NV_CHECK_OK_OR_RETURN(LEVEL_ERROR,
2749         _kgraphicsCtrlCmdGrGetInfoV2(pGpu, pDevice, pParams));
2750 
2751     return NV_OK;
2752 }
2753 
2754 NV_STATUS
kgraphicsDiscoverMaxLocalCtxBufferSize_IMPL(OBJGPU * pGpu,KernelGraphics * pKernelGraphics)2755 kgraphicsDiscoverMaxLocalCtxBufferSize_IMPL
2756 (
2757     OBJGPU *pGpu,
2758     KernelGraphics *pKernelGraphics
2759 )
2760 {
2761     NvU32 bufId = 0;
2762     const KGRAPHICS_STATIC_INFO *pKernelGraphicsStaticInfo = kgraphicsGetStaticInfo(pGpu, pKernelGraphics);
2763 
2764     if (IS_MODS_AMODEL(pGpu))
2765         return NV_OK;
2766 
2767     NV_ASSERT_OK_OR_RETURN(
2768     kgraphicsInitializeDeferredStaticData(pGpu, pKernelGraphics, NV01_NULL_OBJECT, NV01_NULL_OBJECT));
2769 
2770     NV_ASSERT_OR_RETURN(pKernelGraphicsStaticInfo->pContextBuffersInfo != NULL, NV_ERR_INVALID_STATE);
2771 
2772     FOR_EACH_IN_ENUM(GR_CTX_BUFFER, bufId)
2773     {
2774         if (bufId == GR_CTX_BUFFER_MAIN)
2775         {
2776             NvU32 size;
2777 
2778             NV_ASSERT_OK_OR_RETURN(kgraphicsGetMainCtxBufferSize(pGpu, pKernelGraphics, NV_TRUE, &size));
2779             kgraphicsSetCtxBufferInfo(pGpu, pKernelGraphics, bufId,
2780                                       size,
2781                                       RM_PAGE_SIZE,
2782                                       RM_ATTR_PAGE_SIZE_4KB,
2783                                       kgraphicsShouldForceMainCtxContiguity_HAL(pGpu, pKernelGraphics));
2784         }
2785         else
2786         {
2787             NvU32 fifoEngineId;
2788 
2789             NV_ASSERT_OK_OR_RETURN(
2790                 kgrctxCtxBufferToFifoEngineId(bufId, &fifoEngineId));
2791 
2792             kgraphicsSetCtxBufferInfo(pGpu, pKernelGraphics, bufId,
2793                                       pKernelGraphicsStaticInfo->pContextBuffersInfo->engine[fifoEngineId].size,
2794                                       RM_PAGE_SIZE,
2795                                       RM_ATTR_PAGE_SIZE_4KB,
2796                                       ((bufId == GR_CTX_BUFFER_PATCH) || (bufId == GR_CTX_BUFFER_PM)));
2797         }
2798     }
2799     FOR_EACH_IN_ENUM_END;
2800     return NV_OK;
2801 }
2802 
2803 /*!
2804  * KernelGraphics RM SubDevice Controls
2805  */
2806 
2807 /*!
2808  * subdeviceCtrlCmdKGrGetCapsV2
2809  *
2810  * Lock Requirements:
2811  *      Assert that API lock held on entry
2812  */
2813 NV_STATUS
subdeviceCtrlCmdKGrGetCapsV2_IMPL(Subdevice * pSubdevice,NV2080_CTRL_GR_GET_CAPS_V2_PARAMS * pParams)2814 subdeviceCtrlCmdKGrGetCapsV2_IMPL
2815 (
2816     Subdevice *pSubdevice,
2817     NV2080_CTRL_GR_GET_CAPS_V2_PARAMS *pParams
2818 )
2819 {
2820     OBJGPU *pGpu = GPU_RES_GET_GPU(pSubdevice);
2821     KernelGraphicsManager *pKernelGraphicsManager = GPU_GET_KERNEL_GRAPHICS_MANAGER(pGpu);
2822     KernelGraphics *pKernelGraphics;
2823     NV2080_CTRL_GR_ROUTE_INFO grRouteInfo = pParams->grRouteInfo;
2824     Device *pDevice = GPU_RES_GET_DEVICE(pSubdevice);
2825 
2826     kgrmgrCtrlSetEngineID(0, &grRouteInfo);
2827     NV_CHECK_OK_OR_RETURN(LEVEL_ERROR,
2828         kgrmgrCtrlRouteKGRWithDevice(pGpu, pKernelGraphicsManager, pDevice, &grRouteInfo, &pKernelGraphics));
2829 
2830     LOCK_ASSERT_AND_RETURN(rmapiLockIsOwner());
2831 
2832     const KGRAPHICS_STATIC_INFO *pKernelGraphicsStaticInfo = kgraphicsGetStaticInfo(pGpu, pKernelGraphics);
2833     if (pKernelGraphicsStaticInfo == NULL)
2834     {
2835         return NV_ERR_INVALID_STATE;
2836     }
2837 
2838     if (!pParams->bCapsPopulated)
2839     {
2840         NV_CHECK_OK_OR_RETURN(LEVEL_ERROR,
2841             kgraphicsGetCaps(pGpu, pKernelGraphics, pParams->capsTbl));
2842 
2843         pParams->bCapsPopulated = NV_TRUE;
2844     }
2845 
2846     return NV_OK;
2847 }
2848 
2849 /*!
2850  * subdeviceCtrlCmdKGrGetInfo
2851  *
2852  * Lock Requirements:
2853  *      Assert that API lock and GPUs lock held on entry
2854  *
2855  * TODO: remove once all uses have been migrated to V2
2856  */
2857 NV_STATUS
subdeviceCtrlCmdKGrGetInfo_IMPL(Subdevice * pSubdevice,NV2080_CTRL_GR_GET_INFO_PARAMS * pParams)2858 subdeviceCtrlCmdKGrGetInfo_IMPL
2859 (
2860     Subdevice *pSubdevice,
2861     NV2080_CTRL_GR_GET_INFO_PARAMS *pParams
2862 )
2863 {
2864     NV2080_CTRL_GR_GET_INFO_V2_PARAMS grInfoParamsV2;
2865     NV2080_CTRL_GR_INFO *pGrInfos = NvP64_VALUE(pParams->grInfoList);
2866     NV2080_CTRL_GR_ROUTE_INFO grRouteInfo = pParams->grRouteInfo;
2867     OBJGPU *pGpu = GPU_RES_GET_GPU(pSubdevice);
2868     Device *pDevice = GPU_RES_GET_DEVICE(pSubdevice);
2869     NvU32 grInfoListSize = NV_MIN(pParams->grInfoListSize,
2870                                   NV2080_CTRL_GR_INFO_MAX_SIZE);
2871 
2872     //
2873     // Adding the null check as engine GRMGR is missing for DFPGA.
2874     //
2875     KernelGraphicsManager *pKernelGraphicsManager = GPU_GET_KERNEL_GRAPHICS_MANAGER(pGpu);
2876     NV_CHECK_OR_RETURN(LEVEL_ERROR, pKernelGraphicsManager != NULL, NV_ERR_NOT_SUPPORTED);
2877 
2878     LOCK_ASSERT_AND_RETURN(rmapiLockIsOwner() && rmDeviceGpuLockIsOwner(pGpu->gpuInstance));
2879 
2880     NV_CHECK_OR_RETURN(LEVEL_ERROR, pGrInfos != NULL, NV_ERR_INVALID_ARGUMENT);
2881 
2882     portMemSet(&grInfoParamsV2, 0, sizeof(grInfoParamsV2));
2883     grInfoParamsV2.grInfoListSize = grInfoListSize;
2884     portMemCopy(grInfoParamsV2.grInfoList, grInfoListSize * sizeof(*pGrInfos),
2885                 pGrInfos, grInfoListSize * sizeof(*pGrInfos));
2886     grInfoParamsV2.grRouteInfo = grRouteInfo;
2887 
2888     NV_CHECK_OK_OR_RETURN(LEVEL_ERROR,
2889         _kgraphicsCtrlCmdGrGetInfoV2(pGpu, pDevice, &grInfoParamsV2));
2890 
2891     portMemCopy(pGrInfos, grInfoListSize * sizeof(*pGrInfos),
2892                 grInfoParamsV2.grInfoList, grInfoListSize * sizeof(*pGrInfos));
2893     return NV_OK;
2894 }
2895 
2896 /*!
2897  * subdeviceCtrlCmdKGrGetInfoV2
2898  *
2899  * Lock Requirements:
2900  *      Assert that API lock and GPUs lock held on entry
2901  */
2902 NV_STATUS
subdeviceCtrlCmdKGrGetInfoV2_IMPL(Subdevice * pSubdevice,NV2080_CTRL_GR_GET_INFO_V2_PARAMS * pParams)2903 subdeviceCtrlCmdKGrGetInfoV2_IMPL
2904 (
2905     Subdevice *pSubdevice,
2906     NV2080_CTRL_GR_GET_INFO_V2_PARAMS *pParams
2907 )
2908 {
2909     OBJGPU *pGpu = GPU_RES_GET_GPU(pSubdevice);
2910     Device *pDevice = GPU_RES_GET_DEVICE(pSubdevice);
2911 
2912     LOCK_ASSERT_AND_RETURN(rmapiLockIsOwner() && rmDeviceGpuLockIsOwner(pGpu->gpuInstance));
2913 
2914     NV_CHECK_OK_OR_RETURN(LEVEL_ERROR,
2915         _kgraphicsCtrlCmdGrGetInfoV2(pGpu, pDevice, pParams));
2916 
2917     return NV_OK;
2918 }
2919 
2920 /*!
2921  * subdeviceCtrlCmdKGrGetSmToGpcTpcMappings
2922  *
2923  * Lock Requirements:
2924  *      Assert that API lock and GPUs lock held on entry
2925  */
2926 NV_STATUS
subdeviceCtrlCmdKGrGetSmToGpcTpcMappings_IMPL(Subdevice * pSubdevice,NV2080_CTRL_GR_GET_SM_TO_GPC_TPC_MAPPINGS_PARAMS * pParams)2927 subdeviceCtrlCmdKGrGetSmToGpcTpcMappings_IMPL
2928 (
2929     Subdevice *pSubdevice,
2930     NV2080_CTRL_GR_GET_SM_TO_GPC_TPC_MAPPINGS_PARAMS *pParams
2931 )
2932 {
2933     OBJGPU *pGpu = GPU_RES_GET_GPU(pSubdevice);
2934     KernelGraphics *pKernelGraphics;
2935     Device *pDevice = GPU_RES_GET_DEVICE(pSubdevice);
2936     KernelGraphicsManager *pKernelGraphicsManager = GPU_GET_KERNEL_GRAPHICS_MANAGER(pGpu);
2937     KernelMIGManager *pKernelMIGManager = GPU_GET_KERNEL_MIG_MANAGER(pGpu);
2938     const KGRAPHICS_STATIC_INFO *pStaticInfo;
2939     NvU32 i;
2940 
2941     LOCK_ASSERT_AND_RETURN(rmapiLockIsOwner() && rmDeviceGpuLockIsOwner(pGpu->gpuInstance));
2942 
2943     if (kmigmgrIsDeviceUsingDeviceProfiling(pGpu, pKernelMIGManager, pDevice))
2944     {
2945         return NV_ERR_NOT_SUPPORTED;
2946     }
2947     else
2948     {
2949         NV_CHECK_OK_OR_RETURN(LEVEL_ERROR,
2950             kgrmgrCtrlRouteKGRWithDevice(pGpu, pKernelGraphicsManager, pDevice, &pParams->grRouteInfo, &pKernelGraphics));
2951     }
2952 
2953     // Verify static info is available
2954     pStaticInfo = kgraphicsGetStaticInfo(pGpu, pKernelGraphics);
2955     NV_ASSERT_OR_RETURN(pStaticInfo != NULL, NV_ERR_INVALID_STATE);
2956 
2957     // Verify limits are within bounds
2958     NV_ASSERT_OR_RETURN(pStaticInfo->globalSmOrder.numSm <= NV2080_CTRL_GR_GET_SM_TO_GPC_TPC_MAPPINGS_MAX_SM_COUNT,
2959                         NV_ERR_INVALID_LIMIT);
2960 
2961     // Populate output data
2962     pParams->smCount = pStaticInfo->globalSmOrder.numSm;
2963     for (i = 0; i < pStaticInfo->globalSmOrder.numSm; ++i)
2964     {
2965         pParams->smId[i].gpcId = pStaticInfo->globalSmOrder.globalSmId[i].gpcId;
2966         pParams->smId[i].tpcId = pStaticInfo->globalSmOrder.globalSmId[i].localTpcId;
2967     }
2968 
2969     return NV_OK;
2970 }
2971 
2972 NV_STATUS
subdeviceCtrlCmdKGrGetGlobalSmOrder_IMPL(Subdevice * pSubdevice,NV2080_CTRL_GR_GET_GLOBAL_SM_ORDER_PARAMS * pParams)2973 subdeviceCtrlCmdKGrGetGlobalSmOrder_IMPL
2974 (
2975     Subdevice *pSubdevice,
2976     NV2080_CTRL_GR_GET_GLOBAL_SM_ORDER_PARAMS *pParams
2977 )
2978 {
2979     NV_STATUS status = NV_OK;
2980     OBJGPU *pGpu = GPU_RES_GET_GPU(pSubdevice);
2981     KernelGraphics *pKernelGraphics;
2982     Device *pDevice = GPU_RES_GET_DEVICE(pSubdevice);
2983     KernelGraphicsManager *pKernelGraphicsManager = GPU_GET_KERNEL_GRAPHICS_MANAGER(pGpu);
2984     KernelMIGManager *pKernelMIGManager = GPU_GET_KERNEL_MIG_MANAGER(pGpu);
2985     const KGRAPHICS_STATIC_INFO *pStaticInfo;
2986     NvU32 i;
2987 
2988     LOCK_ASSERT_AND_RETURN(rmapiLockIsOwner() && rmDeviceGpuLockIsOwner(pGpu->gpuInstance));
2989 
2990     if (kmigmgrIsDeviceUsingDeviceProfiling(pGpu, pKernelMIGManager, pDevice))
2991     {
2992         return NV_ERR_NOT_SUPPORTED;
2993     }
2994     else
2995     {
2996         NV_CHECK_OK_OR_RETURN(LEVEL_ERROR,
2997             kgrmgrCtrlRouteKGRWithDevice(pGpu, pKernelGraphicsManager, pDevice, &pParams->grRouteInfo, &pKernelGraphics));
2998     }
2999 
3000     // Verify static info is available
3001     pStaticInfo = kgraphicsGetStaticInfo(pGpu, pKernelGraphics);
3002     NV_ASSERT_OR_RETURN(pStaticInfo != NULL, NV_ERR_INVALID_STATE);
3003 
3004     // Verify limits are within bounds
3005     NV_ASSERT_OR_RETURN(pStaticInfo->globalSmOrder.numSm <= NV2080_CTRL_CMD_GR_GET_GLOBAL_SM_ORDER_MAX_SM_COUNT,
3006                         NV_ERR_INVALID_LIMIT);
3007 
3008     // Populate output data
3009     pParams->numSm = pStaticInfo->globalSmOrder.numSm;
3010     pParams->numTpc = pStaticInfo->globalSmOrder.numTpc;
3011     for (i = 0; i < pStaticInfo->globalSmOrder.numSm; ++i)
3012     {
3013         pParams->globalSmId[i].gpcId           = pStaticInfo->globalSmOrder.globalSmId[i].gpcId;
3014         pParams->globalSmId[i].localTpcId      = pStaticInfo->globalSmOrder.globalSmId[i].localTpcId;
3015         pParams->globalSmId[i].localSmId       = pStaticInfo->globalSmOrder.globalSmId[i].localSmId;
3016         pParams->globalSmId[i].globalTpcId     = pStaticInfo->globalSmOrder.globalSmId[i].globalTpcId;
3017         pParams->globalSmId[i].virtualGpcId    = pStaticInfo->globalSmOrder.globalSmId[i].virtualGpcId;
3018         pParams->globalSmId[i].migratableTpcId = pStaticInfo->globalSmOrder.globalSmId[i].migratableTpcId;
3019     }
3020 
3021     return status;
3022 }
3023 
3024 /*!
3025  * subdeviceCtrlCmdKGrGetSmIssueRateModifier
3026  *
3027  * Lock Requirements:
3028  *      Assert that API lock and GPUs lock held on entry
3029  */
3030 NV_STATUS
subdeviceCtrlCmdKGrGetSmIssueRateModifier_IMPL(Subdevice * pSubdevice,NV2080_CTRL_GR_GET_SM_ISSUE_RATE_MODIFIER_PARAMS * pParams)3031 subdeviceCtrlCmdKGrGetSmIssueRateModifier_IMPL
3032 (
3033     Subdevice *pSubdevice,
3034     NV2080_CTRL_GR_GET_SM_ISSUE_RATE_MODIFIER_PARAMS *pParams
3035 )
3036 {
3037     OBJGPU *pGpu = GPU_RES_GET_GPU(pSubdevice);
3038     KernelGraphics *pKernelGraphics;
3039     Device *pDevice = GPU_RES_GET_DEVICE(pSubdevice);
3040     KernelGraphicsManager *pKernelGraphicsManager = GPU_GET_KERNEL_GRAPHICS_MANAGER(pGpu);
3041     const KGRAPHICS_STATIC_INFO *pStaticInfo;
3042     KernelMIGManager *pKernelMIGManager = GPU_GET_KERNEL_MIG_MANAGER(pGpu);
3043 
3044     LOCK_ASSERT_AND_RETURN(rmapiLockIsOwner() && rmGpuLockIsOwner());
3045 
3046     if (kmigmgrIsDeviceUsingDeviceProfiling(pGpu, pKernelMIGManager, pDevice))
3047     {
3048         NvU32 grIdx;
3049         for (grIdx = 0; grIdx < GPU_MAX_GRS; grIdx++)
3050         {
3051             pKernelGraphics = GPU_GET_KERNEL_GRAPHICS(pGpu, grIdx);
3052             if (pKernelGraphics != NULL)
3053                 break;
3054         }
3055         if (pKernelGraphics == NULL)
3056             return NV_ERR_INVALID_STATE;
3057     }
3058     else
3059     {
3060         NV_CHECK_OK_OR_RETURN(LEVEL_ERROR,
3061             kgrmgrCtrlRouteKGRWithDevice(pGpu, pKernelGraphicsManager, pDevice, &pParams->grRouteInfo, &pKernelGraphics));
3062     }
3063 
3064     // Verify static info is available
3065     pStaticInfo = kgraphicsGetStaticInfo(pGpu, pKernelGraphics);
3066     NV_ASSERT_OR_RETURN(pStaticInfo != NULL, NV_ERR_INVALID_STATE);
3067     NV_ASSERT_OR_RETURN(pStaticInfo->pSmIssueRateModifier != NULL, NV_ERR_NOT_SUPPORTED);
3068 
3069     pParams->imla0 = pStaticInfo->pSmIssueRateModifier->imla0;
3070     pParams->fmla16 = pStaticInfo->pSmIssueRateModifier->fmla16;
3071     pParams->dp = pStaticInfo->pSmIssueRateModifier->dp;
3072     pParams->fmla32 = pStaticInfo->pSmIssueRateModifier->fmla32;
3073     pParams->ffma = pStaticInfo->pSmIssueRateModifier->ffma;
3074     pParams->imla1 = pStaticInfo->pSmIssueRateModifier->imla1;
3075     pParams->imla2 = pStaticInfo->pSmIssueRateModifier->imla2;
3076     pParams->imla3 = pStaticInfo->pSmIssueRateModifier->imla3;
3077     pParams->imla4 = pStaticInfo->pSmIssueRateModifier->imla4;
3078 
3079     return NV_OK;
3080 }
3081 
3082 /*!
3083  * subdeviceCtrlCmdKGrGetGpcMask
3084  *
3085  * Lock Requirements:
3086  *      Assert that API lock and GPUs lock held on entry
3087  */
3088 NV_STATUS
subdeviceCtrlCmdKGrGetGpcMask_IMPL(Subdevice * pSubdevice,NV2080_CTRL_GR_GET_GPC_MASK_PARAMS * pParams)3089 subdeviceCtrlCmdKGrGetGpcMask_IMPL
3090 (
3091     Subdevice *pSubdevice,
3092     NV2080_CTRL_GR_GET_GPC_MASK_PARAMS *pParams
3093 )
3094 {
3095     NV_STATUS status = NV_OK;
3096     OBJGPU *pGpu = GPU_RES_GET_GPU(pSubdevice);
3097     Device *pDevice = GPU_RES_GET_DEVICE(pSubdevice);
3098     KernelGraphicsManager *pKernelGraphicsManager = GPU_GET_KERNEL_GRAPHICS_MANAGER(pGpu);
3099     KernelGraphics *pKernelGraphics;
3100     const KGRAPHICS_STATIC_INFO *pKernelGraphicsStaticInfo;
3101     KernelMIGManager *pKernelMIGManager = GPU_GET_KERNEL_MIG_MANAGER(pGpu);
3102 
3103     LOCK_ASSERT_AND_RETURN(rmapiLockIsOwner() && rmDeviceGpuLockIsOwner(pGpu->gpuInstance));
3104 
3105     if (!IS_MIG_IN_USE(pGpu) ||
3106         kmigmgrIsDeviceUsingDeviceProfiling(pGpu, pKernelMIGManager, pDevice))
3107     {
3108         pParams->gpcMask = kgrmgrGetLegacyGpcMask(pGpu, pKernelGraphicsManager);
3109     }
3110     else
3111     {
3112         NV_CHECK_OK_OR_RETURN(LEVEL_ERROR,
3113             kgrmgrCtrlRouteKGRWithDevice(pGpu, pKernelGraphicsManager, pDevice, &pParams->grRouteInfo, &pKernelGraphics));
3114 
3115         pKernelGraphicsStaticInfo = kgraphicsGetStaticInfo(pGpu, pKernelGraphics);
3116         NV_ASSERT_OR_RETURN(pKernelGraphicsStaticInfo != NULL, NV_ERR_INVALID_STATE);
3117 
3118         pParams->gpcMask = pKernelGraphicsStaticInfo->floorsweepingMasks.gpcMask;
3119     }
3120 
3121     return status;
3122 }
3123 
3124 /*!
3125  * subdeviceCtrlCmdKGrGetTpcMask
3126  *
3127  * Note:
3128  *   pParams->gpcId is physical GPC id for non-MIG case, but logical GPC id for
3129  *   MIG case.
3130  *
3131  * Lock Requirements:
3132  *      Assert that API lock and GPUs lock held on entry
3133  */
3134 NV_STATUS
subdeviceCtrlCmdKGrGetTpcMask_IMPL(Subdevice * pSubdevice,NV2080_CTRL_GR_GET_TPC_MASK_PARAMS * pParams)3135 subdeviceCtrlCmdKGrGetTpcMask_IMPL
3136 (
3137     Subdevice *pSubdevice,
3138     NV2080_CTRL_GR_GET_TPC_MASK_PARAMS *pParams
3139 )
3140 {
3141     NV_STATUS status = NV_OK;
3142     OBJGPU *pGpu = GPU_RES_GET_GPU(pSubdevice);
3143     Device *pDevice = GPU_RES_GET_DEVICE(pSubdevice);
3144     KernelGraphicsManager *pKernelGraphicsManager = GPU_GET_KERNEL_GRAPHICS_MANAGER(pGpu);
3145     KernelGraphics *pKernelGraphics;
3146     const KGRAPHICS_STATIC_INFO *pKernelGraphicsStaticInfo;
3147     KernelMIGManager *pKernelMIGManager = GPU_GET_KERNEL_MIG_MANAGER(pGpu);
3148     NvU32 gpcCount;
3149 
3150     LOCK_ASSERT_AND_RETURN(rmapiLockIsOwner() && rmDeviceGpuLockIsOwner(pGpu->gpuInstance));
3151 
3152     if (!IS_MIG_IN_USE(pGpu) ||
3153         kmigmgrIsDeviceUsingDeviceProfiling(pGpu, pKernelMIGManager, pDevice))
3154     {
3155         pParams->tpcMask = kgrmgrGetLegacyTpcMask(pGpu, pKernelGraphicsManager, pParams->gpcId);
3156     }
3157     else
3158     {
3159         NV_CHECK_OK_OR_RETURN(LEVEL_ERROR,
3160             kgrmgrCtrlRouteKGRWithDevice(pGpu, pKernelGraphicsManager, pDevice, &pParams->grRouteInfo, &pKernelGraphics));
3161 
3162         pKernelGraphicsStaticInfo = kgraphicsGetStaticInfo(pGpu, pKernelGraphics);
3163         NV_ASSERT_OR_RETURN(pKernelGraphicsStaticInfo != NULL, NV_ERR_INVALID_STATE);
3164 
3165         gpcCount = nvPopCount32(pKernelGraphicsStaticInfo->floorsweepingMasks.gpcMask);
3166         if (pParams->gpcId >= gpcCount)
3167         {
3168             NV_PRINTF(LEVEL_ERROR, "Incorrect GPC-Idx provided = %d\n", pParams->gpcId);
3169             return NV_ERR_INVALID_ARGUMENT;
3170         }
3171 
3172         pParams->tpcMask = pKernelGraphicsStaticInfo->floorsweepingMasks.tpcMask[pParams->gpcId];
3173     }
3174 
3175     return status;
3176 }
3177 
3178 NV_STATUS
subdeviceCtrlCmdKGrGetNumTpcsForGpc_IMPL(Subdevice * pSubdevice,NV2080_CTRL_GR_GET_NUM_TPCS_FOR_GPC_PARAMS * pParams)3179 subdeviceCtrlCmdKGrGetNumTpcsForGpc_IMPL
3180 (
3181     Subdevice *pSubdevice,
3182     NV2080_CTRL_GR_GET_NUM_TPCS_FOR_GPC_PARAMS *pParams
3183 )
3184 {
3185     OBJGPU *pGpu = GPU_RES_GET_GPU(pSubdevice);
3186     Device *pDevice = GPU_RES_GET_DEVICE(pSubdevice);
3187     KernelGraphicsManager *pKernelGraphicsManager = GPU_GET_KERNEL_GRAPHICS_MANAGER(pGpu);
3188     KernelGraphics *pKernelGraphics;
3189     const KGRAPHICS_STATIC_INFO *pKernelGraphicsStaticInfo;
3190     NV2080_CTRL_GR_ROUTE_INFO grRouteInfo;
3191     NvU32 gpcCount;
3192 
3193     portMemSet(&grRouteInfo, 0, sizeof(grRouteInfo));
3194     NV_CHECK_OK_OR_RETURN(LEVEL_ERROR,
3195         kgrmgrCtrlRouteKGRWithDevice(pGpu, pKernelGraphicsManager, pDevice, &grRouteInfo, &pKernelGraphics));
3196 
3197     pKernelGraphicsStaticInfo = kgraphicsGetStaticInfo(pGpu, pKernelGraphics);
3198     NV_ASSERT_OR_RETURN(pKernelGraphicsStaticInfo != NULL, NV_ERR_INVALID_STATE);
3199 
3200     gpcCount = nvPopCount32(pKernelGraphicsStaticInfo->floorsweepingMasks.gpcMask);
3201     if (pParams->gpcId >= gpcCount)
3202     {
3203         NV_PRINTF(LEVEL_ERROR, "Incorrect GPC-Idx provided = %d\n", pParams->gpcId);
3204         return NV_ERR_INVALID_ARGUMENT;
3205     }
3206 
3207     pParams->numTpcs = pKernelGraphicsStaticInfo->floorsweepingMasks.tpcCount[pParams->gpcId];
3208 
3209     return NV_OK;
3210 }
3211 
3212 /*!
3213  * subdeviceCtrlCmdKGrGetPpcMask
3214  *
3215  * Lock Requirements:
3216  *      Assert that API lock and GPUs lock held on entry
3217  */
3218 NV_STATUS
subdeviceCtrlCmdKGrGetPpcMask_IMPL(Subdevice * pSubdevice,NV2080_CTRL_GR_GET_PPC_MASK_PARAMS * pParams)3219 subdeviceCtrlCmdKGrGetPpcMask_IMPL
3220 (
3221     Subdevice *pSubdevice,
3222     NV2080_CTRL_GR_GET_PPC_MASK_PARAMS *pParams
3223 )
3224 {
3225     OBJGPU *pGpu = GPU_RES_GET_GPU(pSubdevice);
3226     Device *pDevice = GPU_RES_GET_DEVICE(pSubdevice);
3227     KernelGraphicsManager *pKernelGraphicsManager = GPU_GET_KERNEL_GRAPHICS_MANAGER(pGpu);
3228     KernelGraphics *pKernelGraphics;
3229     const KGRAPHICS_STATIC_INFO *pKernelGraphicsStaticInfo;
3230     KernelMIGManager *pKernelMIGManager = GPU_GET_KERNEL_MIG_MANAGER(pGpu);
3231 
3232     LOCK_ASSERT_AND_RETURN(rmapiLockIsOwner() && rmDeviceGpuLockIsOwner(pGpu->gpuInstance));
3233 
3234     if (kmigmgrIsDeviceUsingDeviceProfiling(pGpu, pKernelMIGManager, pDevice))
3235     {
3236         NV_CHECK_OK_OR_RETURN(LEVEL_ERROR, kgrmgrGetLegacyPpcMask(pGpu, pKernelGraphicsManager, pParams->gpcId, &pParams->ppcMask));
3237     }
3238     else
3239     {
3240         NV_CHECK_OK_OR_RETURN(LEVEL_ERROR,
3241             kgrmgrCtrlRouteKGRWithDevice(pGpu, pKernelGraphicsManager, pDevice, &pParams->grRouteInfo, &pKernelGraphics));
3242 
3243         pKernelGraphicsStaticInfo = kgraphicsGetStaticInfo(pGpu, pKernelGraphics);
3244         NV_ASSERT_OR_RETURN(pKernelGraphicsStaticInfo != NULL, NV_ERR_INVALID_STATE);
3245         NV_ASSERT_OR_RETURN(pKernelGraphicsStaticInfo->pPpcMasks != NULL, NV_ERR_NOT_SUPPORTED);
3246         NV_ASSERT_OR_RETURN(pKernelGraphicsStaticInfo->pGrInfo != NULL, NV_ERR_NOT_SUPPORTED);
3247 
3248         if (pParams->gpcId >=
3249             pKernelGraphicsStaticInfo->pGrInfo->infoList[NV2080_CTRL_GR_INFO_INDEX_LITTER_NUM_GPCS].data)
3250         {
3251             NV_PRINTF(LEVEL_ERROR, "Incorrect GPC-Idx provided = %d\n", pParams->gpcId);
3252             return NV_ERR_INVALID_ARGUMENT;
3253         }
3254 
3255         pParams->ppcMask = pKernelGraphicsStaticInfo->pPpcMasks->mask[pParams->gpcId];
3256     }
3257 
3258     return NV_OK;
3259 }
3260 
3261 //
3262 // subdeviceCtrlCmdKGrFecsBindEvtbufForUid
3263 //
3264 // Lock Requirements:
3265 //      Assert that API lock and GPUs lock held on entry
3266 //
3267 NV_STATUS
subdeviceCtrlCmdKGrFecsBindEvtbufForUid_IMPL(Subdevice * pSubdevice,NV2080_CTRL_GR_FECS_BIND_EVTBUF_FOR_UID_PARAMS * pParams)3268 subdeviceCtrlCmdKGrFecsBindEvtbufForUid_IMPL
3269 (
3270     Subdevice *pSubdevice,
3271     NV2080_CTRL_GR_FECS_BIND_EVTBUF_FOR_UID_PARAMS *pParams
3272 )
3273 {
3274     NV_STATUS status;
3275     RmClient *pClient;
3276     RsResourceRef *pEventBufferRef = NULL;
3277     OBJGPU *pGpu = GPU_RES_GET_GPU(pSubdevice);
3278     NvHandle hClient = RES_GET_CLIENT_HANDLE(pSubdevice);
3279     NvBool bMIGInUse = IS_MIG_IN_USE(pGpu);
3280 
3281     LOCK_ASSERT_AND_RETURN(rmapiLockIsOwner() && rmDeviceGpuLockIsOwner(pGpu->gpuInstance));
3282 
3283     NV_ASSERT_OK_OR_RETURN(
3284         serverutilGetResourceRefWithType(hClient, pParams->hEventBuffer, classId(EventBuffer), &pEventBufferRef));
3285 
3286     pClient = serverutilGetClientUnderLock(hClient);
3287     NV_ASSERT_OR_RETURN(pClient != NULL, NV_ERR_INVALID_CLIENT);
3288 
3289     if (bMIGInUse)
3290         return NV_ERR_NOT_SUPPORTED;
3291 
3292     status = fecsAddBindpoint(pGpu,
3293                               pClient,
3294                               pEventBufferRef,
3295                               pSubdevice,
3296                               pParams->bAllUsers,
3297                               pParams->levelOfDetail,
3298                               pParams->eventFilter,
3299                               1,
3300                               NULL);
3301 
3302     return status;
3303 }
3304 
3305 //
3306 // subdeviceCtrlCmdKGrFecsBindEvtbufForUidV2
3307 //
3308 // Lock Requirements:
3309 //      Assert that API lock and GPUs lock held on entry
3310 //
3311 NV_STATUS
subdeviceCtrlCmdKGrFecsBindEvtbufForUidV2_IMPL(Subdevice * pSubdevice,NV2080_CTRL_GR_FECS_BIND_EVTBUF_FOR_UID_V2_PARAMS * pParams)3312 subdeviceCtrlCmdKGrFecsBindEvtbufForUidV2_IMPL
3313 (
3314     Subdevice *pSubdevice,
3315     NV2080_CTRL_GR_FECS_BIND_EVTBUF_FOR_UID_V2_PARAMS *pParams
3316 )
3317 {
3318     NV_STATUS status;
3319     RmClient *pClient;
3320     RsResourceRef *pEventBufferRef = NULL;
3321     OBJGPU *pGpu = GPU_RES_GET_GPU(pSubdevice);
3322     NvHandle hClient = RES_GET_CLIENT_HANDLE(pSubdevice);
3323     pParams->reasonCode = NV2080_CTRL_GR_FECS_BIND_REASON_CODE_NONE;
3324 
3325     LOCK_ASSERT_AND_RETURN(rmapiLockIsOwner() && rmDeviceGpuLockIsOwner(pGpu->gpuInstance));
3326 
3327     NV_ASSERT_OK_OR_RETURN(
3328         serverutilGetResourceRefWithType(hClient, pParams->hEventBuffer, classId(EventBuffer), &pEventBufferRef));
3329 
3330     pClient = serverutilGetClientUnderLock(hClient);
3331     NV_ASSERT_OR_RETURN(pClient != NULL, NV_ERR_INVALID_CLIENT);
3332 
3333     status = fecsAddBindpoint(pGpu,
3334                               pClient,
3335                               pEventBufferRef,
3336                               pSubdevice,
3337                               pParams->bAllUsers,
3338                               pParams->levelOfDetail,
3339                               pParams->eventFilter,
3340                               2,
3341                               &pParams->reasonCode);
3342     return status;
3343 }
3344 
3345 /*!
3346  * subdeviceCtrlCmdKGrGetPhysGpcMask
3347  *
3348  * Lock Requirements:
3349  *      Assert that API lock and GPUs lock held on entry
3350  */
3351 NV_STATUS
subdeviceCtrlCmdKGrGetPhysGpcMask_IMPL(Subdevice * pSubdevice,NV2080_CTRL_GR_GET_PHYS_GPC_MASK_PARAMS * pParams)3352 subdeviceCtrlCmdKGrGetPhysGpcMask_IMPL
3353 (
3354     Subdevice *pSubdevice,
3355     NV2080_CTRL_GR_GET_PHYS_GPC_MASK_PARAMS *pParams
3356 )
3357 {
3358     OBJGPU *pGpu = GPU_RES_GET_GPU(pSubdevice);
3359     KernelGraphics *pKernelGraphics;
3360     const KGRAPHICS_STATIC_INFO *pKernelGraphicsStaticInfo;
3361     Device *pDevice = GPU_RES_GET_DEVICE(pSubdevice);
3362     KernelMIGManager *pKernelMIGManager = GPU_GET_KERNEL_MIG_MANAGER(pGpu);
3363     NvU32 grIdx = 0;
3364 
3365     LOCK_ASSERT_AND_RETURN(rmapiLockIsOwner() && rmDeviceGpuLockIsOwner(pGpu->gpuInstance));
3366 
3367     if (!IS_MIG_ENABLED(pGpu))
3368     {
3369         grIdx = 0;
3370     }
3371     //
3372     // if MIG is enabled we follow below policies:
3373     // For device level monitoring with no subscription - Return GPC mask for
3374     //                                                    requested syspipe
3375     // For valid subscription - Return physical GPC mask after validating that
3376     //                           a physical syspipe exist in given GPU instance
3377     //
3378     else if (kmigmgrIsDeviceUsingDeviceProfiling(pGpu, pKernelMIGManager, pDevice))
3379     {
3380         NV_ASSERT_OR_RETURN(pParams->physSyspipeId < GPU_MAX_GRS, NV_ERR_INVALID_ARGUMENT);
3381         grIdx = pParams->physSyspipeId;
3382     }
3383     else
3384     {
3385         MIG_INSTANCE_REF ref;
3386         RM_ENGINE_TYPE localRmEngineType;
3387 
3388         //
3389         // Get the relevant subscription and see if provided physicalId is
3390         // valid in defined GPU instance
3391         //
3392         NV_CHECK_OK_OR_RETURN(LEVEL_ERROR,
3393                               kmigmgrGetInstanceRefFromDevice(pGpu, pKernelMIGManager,
3394                                                               pDevice, &ref));
3395 
3396         NV_CHECK_OK_OR_RETURN(LEVEL_ERROR,
3397                               kmigmgrGetGlobalToLocalEngineType(pGpu, pKernelMIGManager, ref,
3398                                                                 RM_ENGINE_TYPE_GR(pParams->physSyspipeId),
3399                                                                 &localRmEngineType));
3400         // Not failing above means physSyspipeId is valid in GPU instance
3401         grIdx = pParams->physSyspipeId;
3402     }
3403 
3404     pKernelGraphics = GPU_GET_KERNEL_GRAPHICS(pGpu, grIdx);
3405     NV_ASSERT_OR_RETURN(pKernelGraphics != NULL, NV_ERR_INVALID_STATE);
3406     pKernelGraphicsStaticInfo = kgraphicsGetStaticInfo(pGpu, pKernelGraphics);
3407     NV_ASSERT_OR_RETURN(pKernelGraphicsStaticInfo != NULL, NV_ERR_INVALID_STATE);
3408 
3409     pParams->gpcMask = pKernelGraphicsStaticInfo->floorsweepingMasks.physGpcMask;
3410 
3411     return NV_OK;
3412 }
3413 
3414 /*!
3415  * subdeviceCtrlCmdKGrGetZcullMask_IMPL
3416  *
3417  * Lock Requirements:
3418  *      Assert that API lock and GPUs lock held on entry
3419  */
3420 NV_STATUS
subdeviceCtrlCmdKGrGetZcullMask_IMPL(Subdevice * pSubdevice,NV2080_CTRL_GR_GET_ZCULL_MASK_PARAMS * pParams)3421 subdeviceCtrlCmdKGrGetZcullMask_IMPL
3422 (
3423     Subdevice *pSubdevice,
3424     NV2080_CTRL_GR_GET_ZCULL_MASK_PARAMS *pParams
3425 )
3426 {
3427     OBJGPU *pGpu = GPU_RES_GET_GPU(pSubdevice);
3428     Device *pDevice = GPU_RES_GET_DEVICE(pSubdevice);
3429     KernelGraphicsManager *pKernelGraphicsManager = GPU_GET_KERNEL_GRAPHICS_MANAGER(pGpu);
3430     NV2080_CTRL_GR_ROUTE_INFO grRouteInfo;
3431     KernelGraphics *pKernelGraphics;
3432     const KGRAPHICS_STATIC_INFO *pKernelGraphicsStaticInfo;
3433     KernelMIGManager *pKernelMIGManager = GPU_GET_KERNEL_MIG_MANAGER(pGpu);
3434 
3435     LOCK_ASSERT_AND_RETURN(rmapiLockIsOwner() && rmDeviceGpuLockIsOwner(pGpu->gpuInstance));
3436 
3437     if (kmigmgrIsDeviceUsingDeviceProfiling(pGpu, pKernelMIGManager, pDevice))
3438     {
3439         pParams->zcullMask = kgrmgrGetLegacyZcullMask(pGpu, pKernelGraphicsManager, pParams->gpcId);
3440     }
3441     else
3442     {
3443         portMemSet(&grRouteInfo, 0, sizeof(grRouteInfo));
3444         NV_CHECK_OK_OR_RETURN(LEVEL_ERROR,
3445             kgrmgrCtrlRouteKGRWithDevice(pGpu, pKernelGraphicsManager, pDevice, &grRouteInfo, &pKernelGraphics));
3446 
3447         pKernelGraphicsStaticInfo = kgraphicsGetStaticInfo(pGpu, pKernelGraphics);
3448         NV_ASSERT_OR_RETURN(pKernelGraphicsStaticInfo != NULL, NV_ERR_INVALID_STATE);
3449 
3450         if (pParams->gpcId >=
3451             pKernelGraphicsStaticInfo->pGrInfo->infoList[NV2080_CTRL_GR_INFO_INDEX_LITTER_NUM_GPCS].data)
3452         {
3453             NV_PRINTF(LEVEL_ERROR, "Incorrect GPC-Idx provided = %d\n", pParams->gpcId);
3454             return NV_ERR_INVALID_ARGUMENT;
3455         }
3456 
3457         if (pKernelGraphicsStaticInfo->floorsweepingMasks.zcullMask[pParams->gpcId] == NV_U32_MAX)
3458         {
3459             return NV_ERR_NOT_SUPPORTED;
3460         }
3461         else
3462         {
3463             pParams->zcullMask = pKernelGraphicsStaticInfo->floorsweepingMasks.zcullMask[pParams->gpcId];
3464         }
3465     }
3466 
3467     return NV_OK;
3468 }
3469 
3470 /*!
3471  * subdeviceCtrlCmdKGrGetZcullInfo
3472  *
3473  * Lock Requirements:
3474  *      Assert that API lock held on entry
3475  */
3476 NV_STATUS
subdeviceCtrlCmdKGrGetZcullInfo_IMPL(Subdevice * pSubdevice,NV2080_CTRL_GR_GET_ZCULL_INFO_PARAMS * pParams)3477 subdeviceCtrlCmdKGrGetZcullInfo_IMPL
3478 (
3479     Subdevice *pSubdevice,
3480     NV2080_CTRL_GR_GET_ZCULL_INFO_PARAMS *pParams
3481 )
3482 {
3483     OBJGPU *pGpu = GPU_RES_GET_GPU(pSubdevice);
3484     KernelGraphicsManager *pKernelGraphicsManager = GPU_GET_KERNEL_GRAPHICS_MANAGER(pGpu);
3485     Device *pDevice = GPU_RES_GET_DEVICE(pSubdevice);
3486     NV2080_CTRL_GR_ROUTE_INFO grRouteInfo;
3487     KernelGraphics *pKernelGraphics;
3488     const KGRAPHICS_STATIC_INFO *pKernelGraphicsStaticInfo;
3489 
3490     LOCK_ASSERT_AND_RETURN(rmapiLockIsOwner());
3491 
3492     if (pKernelGraphicsManager == NULL)
3493     {
3494         return NV_ERR_NOT_SUPPORTED;
3495     }
3496 
3497     portMemSet(&grRouteInfo, 0, sizeof(grRouteInfo));
3498     NV_CHECK_OK_OR_RETURN(LEVEL_ERROR,
3499         kgrmgrCtrlRouteKGRWithDevice(pGpu, pKernelGraphicsManager, pDevice, &grRouteInfo, &pKernelGraphics));
3500 
3501     pKernelGraphicsStaticInfo = kgraphicsGetStaticInfo(pGpu, pKernelGraphics);
3502     NV_ASSERT_OR_RETURN(pKernelGraphicsStaticInfo != NULL, NV_ERR_INVALID_STATE);
3503     NV_ASSERT_OR_RETURN(pKernelGraphicsStaticInfo->pZcullInfo != NULL, NV_ERR_NOT_SUPPORTED);
3504 
3505     portMemCopy(pParams,
3506                 sizeof(*pParams),
3507                 pKernelGraphicsStaticInfo->pZcullInfo,
3508                 sizeof(*pKernelGraphicsStaticInfo->pZcullInfo));
3509 
3510     return NV_OK;
3511 }
3512 
3513 NV_STATUS
subdeviceCtrlCmdKGrCtxswPmMode_IMPL(Subdevice * pSubdevice,NV2080_CTRL_GR_CTXSW_PM_MODE_PARAMS * pParams)3514 subdeviceCtrlCmdKGrCtxswPmMode_IMPL
3515 (
3516     Subdevice *pSubdevice,
3517     NV2080_CTRL_GR_CTXSW_PM_MODE_PARAMS *pParams
3518 )
3519 {
3520     OBJGPU *pGpu = GPU_RES_GET_GPU(pSubdevice);
3521     NV_STATUS status = NV_OK;
3522 
3523     if (IS_GSP_CLIENT(pGpu))
3524     {
3525         NV2080_CTRL_GR_ROUTE_INFO grRouteInfo = pParams->grRouteInfo;
3526         KernelGraphicsManager *pKernelGraphicsManager = GPU_GET_KERNEL_GRAPHICS_MANAGER(pGpu);
3527         KernelGraphics *pKernelGraphics;
3528         KernelChannel *pKernelChannel;
3529         KernelGraphicsContext *pKernelGraphicsContext;
3530         RM_API *pRmApi = GPU_GET_PHYSICAL_RMAPI(pGpu);
3531 
3532         LOCK_ASSERT_AND_RETURN(rmapiLockIsOwner() && rmDeviceGpuLockIsOwner(pGpu->gpuInstance));
3533 
3534         if (pParams->pmMode != NV2080_CTRL_CTXSW_PM_MODE_NO_CTXSW)
3535         {
3536             kgrmgrCtrlSetChannelHandle(pParams->hChannel, &grRouteInfo);
3537             NV_CHECK_OK_OR_RETURN(LEVEL_ERROR,
3538                 kgrmgrCtrlRouteKGRWithDevice(pGpu, pKernelGraphicsManager,
3539                                              GPU_RES_GET_DEVICE(pSubdevice),
3540                                              &grRouteInfo,
3541                                              &pKernelGraphics));
3542 
3543             // Retrieve channel from either bare channel or TSG handle
3544             NV_CHECK_OK_OR_RETURN(LEVEL_ERROR,
3545                 kchannelGetFromDualHandleRestricted(RES_GET_CLIENT(pSubdevice),
3546                     pParams->hChannel, &pKernelChannel));
3547 
3548             NV_ASSERT_OK_OR_RETURN(
3549                 kgrctxFromKernelChannel(pKernelChannel, &pKernelGraphicsContext));
3550 
3551             // Setup / promote the PM ctx buffer if required
3552             NV_CHECK_OK_OR_RETURN(LEVEL_ERROR,
3553                 kgrctxSetupDeferredPmBuffer(pGpu, pKernelGraphicsContext, pKernelGraphics, pKernelChannel));
3554         }
3555 
3556         status = pRmApi->Control(pRmApi,
3557                                  RES_GET_CLIENT_HANDLE(pSubdevice),
3558                                  RES_GET_HANDLE(pSubdevice),
3559                                  NV2080_CTRL_CMD_GR_CTXSW_PM_MODE,
3560                                  pParams,
3561                                  sizeof(*pParams));
3562     }
3563 
3564     return status;
3565 }
3566 
3567 /*!
3568  * @brief Gets information about ROPs.
3569  *
3570  *        Lock Requirements:
3571  *          Assert that API and Gpus lock held on entry
3572  *
3573  * @return    NV_OK if success. Error otherwise.
3574  */
3575 NV_STATUS
subdeviceCtrlCmdKGrGetROPInfo_IMPL(Subdevice * pSubdevice,NV2080_CTRL_GR_GET_ROP_INFO_PARAMS * pRopInfoParams)3576 subdeviceCtrlCmdKGrGetROPInfo_IMPL
3577 (
3578     Subdevice *pSubdevice,
3579     NV2080_CTRL_GR_GET_ROP_INFO_PARAMS *pRopInfoParams
3580 )
3581 {
3582     OBJGPU *pGpu = GPU_RES_GET_GPU(pSubdevice);
3583     KernelGraphicsManager *pKernelGraphicsManager = GPU_GET_KERNEL_GRAPHICS_MANAGER(pGpu);
3584     Device *pDevice = GPU_RES_GET_DEVICE(pSubdevice);
3585     NV2080_CTRL_GR_ROUTE_INFO grRouteInfo;
3586     KernelGraphics *pKernelGraphics;
3587     const KGRAPHICS_STATIC_INFO *pKernelGraphicsStaticInfo;
3588 
3589     LOCK_ASSERT_AND_RETURN(rmapiLockIsOwner());
3590 
3591     portMemSet(&grRouteInfo, 0, sizeof(grRouteInfo));
3592     NV_CHECK_OK_OR_RETURN(LEVEL_ERROR,
3593         kgrmgrCtrlRouteKGRWithDevice(pGpu, pKernelGraphicsManager, pDevice, &grRouteInfo, &pKernelGraphics));
3594 
3595     pKernelGraphicsStaticInfo = kgraphicsGetStaticInfo(pGpu, pKernelGraphics);
3596     NV_ASSERT_OR_RETURN(pKernelGraphicsStaticInfo != NULL, NV_ERR_INVALID_STATE);
3597     NV_ASSERT_OR_RETURN(pKernelGraphicsStaticInfo->pRopInfo != NULL, NV_ERR_NOT_SUPPORTED);
3598 
3599     portMemCopy(pRopInfoParams,
3600                 sizeof(*pRopInfoParams),
3601                 pKernelGraphicsStaticInfo->pRopInfo,
3602                 sizeof(*pKernelGraphicsStaticInfo->pRopInfo));
3603 
3604     return NV_OK;
3605 }
3606 
3607 /*!
3608  * @brief Gets the current attribute buffer size.
3609  *
3610  * Lock Requirements:
3611  *  Assert that API lock held on entry
3612  *
3613  * @return    NV_OK if success. Error otherwise.
3614  */
3615 NV_STATUS
subdeviceCtrlCmdKGrGetAttributeBufferSize_IMPL(Subdevice * pSubdevice,NV2080_CTRL_GR_GET_ATTRIBUTE_BUFFER_SIZE_PARAMS * pAttribBufferSizeParams)3616 subdeviceCtrlCmdKGrGetAttributeBufferSize_IMPL
3617 (
3618     Subdevice *pSubdevice,
3619     NV2080_CTRL_GR_GET_ATTRIBUTE_BUFFER_SIZE_PARAMS *pAttribBufferSizeParams
3620 )
3621 {
3622     OBJGPU *pGpu = GPU_RES_GET_GPU(pSubdevice);
3623     KernelGraphicsManager *pKernelGraphicsManager = GPU_GET_KERNEL_GRAPHICS_MANAGER(pGpu);
3624     NV2080_CTRL_GR_ROUTE_INFO grRouteInfo;
3625     KernelGraphics *pKernelGraphics;
3626     const KGRAPHICS_STATIC_INFO *pKernelGraphicsStaticInfo;
3627     Device *pDevice = GPU_RES_GET_DEVICE(pSubdevice);
3628     NvU32 engineId;
3629 
3630     LOCK_ASSERT_AND_RETURN(rmapiLockIsOwner() && rmGpuLockIsOwner());
3631 
3632     portMemSet(&grRouteInfo, 0, sizeof(grRouteInfo));
3633     NV_CHECK_OK_OR_RETURN(LEVEL_ERROR,
3634         kgrmgrCtrlRouteKGRWithDevice(pGpu, pKernelGraphicsManager, pDevice, &grRouteInfo, &pKernelGraphics));
3635 
3636     // Verify static info is available
3637     pKernelGraphicsStaticInfo = kgraphicsGetStaticInfo(pGpu, pKernelGraphics);
3638     NV_ASSERT_OR_RETURN(pKernelGraphicsStaticInfo != NULL, NV_ERR_INVALID_STATE);
3639 
3640     if (pKernelGraphicsStaticInfo->pContextBuffersInfo == NULL)
3641     {
3642         NV_CHECK_OK_OR_RETURN(LEVEL_ERROR,
3643             kgraphicsInitializeDeferredStaticData(pGpu, pKernelGraphics, NV01_NULL_OBJECT, NV01_NULL_OBJECT));
3644 
3645         NV_ASSERT_OR_RETURN(pKernelGraphicsStaticInfo->pContextBuffersInfo != NULL, NV_ERR_INVALID_STATE);
3646     }
3647 
3648     engineId = NV0080_CTRL_FIFO_GET_ENGINE_CONTEXT_PROPERTIES_ENGINE_ID_GRAPHICS_ATTRIBUTE_CB;
3649     pAttribBufferSizeParams->attribBufferSize = pKernelGraphicsStaticInfo->pContextBuffersInfo->engine[engineId].size;
3650 
3651     return NV_OK;
3652 }
3653 
3654 /*!
3655  * subdeviceCtrlCmdKGrGetEngineContextProperties
3656  *
3657  * Lock Requirements:
3658  *      Assert that API lock and GPUs lock held on entry
3659  */
3660 NV_STATUS
subdeviceCtrlCmdKGrGetEngineContextProperties_IMPL(Subdevice * pSubdevice,NV2080_CTRL_GR_GET_ENGINE_CONTEXT_PROPERTIES_PARAMS * pParams)3661 subdeviceCtrlCmdKGrGetEngineContextProperties_IMPL
3662 (
3663     Subdevice *pSubdevice,
3664     NV2080_CTRL_GR_GET_ENGINE_CONTEXT_PROPERTIES_PARAMS *pParams
3665 )
3666 {
3667     OBJGPU *pGpu = GPU_RES_GET_GPU(pSubdevice);
3668     KernelGraphicsManager *pKernelGraphicsManager = GPU_GET_KERNEL_GRAPHICS_MANAGER(pGpu);
3669     KernelGraphics *pKernelGraphics;
3670     const KGRAPHICS_STATIC_INFO *pKernelGraphicsStaticInfo;
3671     Device *pDevice = GPU_RES_GET_DEVICE(pSubdevice);
3672     NvU32 size = 0;
3673     NvU32 alignment = RM_PAGE_SIZE;
3674     NvU32 engineId;
3675 
3676     LOCK_ASSERT_AND_RETURN(rmapiLockIsOwner() && rmGpuLockIsOwner());
3677 
3678     engineId = DRF_VAL(0080_CTRL_FIFO, _GET_ENGINE_CONTEXT_PROPERTIES, _ENGINE_ID, pParams->engineId);
3679 
3680     if (engineId >= NV0080_CTRL_FIFO_GET_ENGINE_CONTEXT_PROPERTIES_ENGINE_ID_COUNT)
3681     {
3682         return NV_ERR_INVALID_ARGUMENT;
3683     }
3684 
3685     NV_CHECK_OK_OR_RETURN(LEVEL_ERROR,
3686         kgrmgrCtrlRouteKGRWithDevice(pGpu, pKernelGraphicsManager, pDevice,
3687                                      &pParams->grRouteInfo, &pKernelGraphics));
3688 
3689     // Verify static info is available
3690     pKernelGraphicsStaticInfo = kgraphicsGetStaticInfo(pGpu, pKernelGraphics);
3691     NV_ASSERT_OR_RETURN(pKernelGraphicsStaticInfo != NULL, NV_ERR_INVALID_STATE);
3692 
3693     if (pKernelGraphicsStaticInfo->pContextBuffersInfo == NULL)
3694     {
3695         NV_CHECK_OK_OR_RETURN(LEVEL_ERROR,
3696             kgraphicsInitializeDeferredStaticData(pGpu, pKernelGraphics, NV01_NULL_OBJECT, NV01_NULL_OBJECT));
3697 
3698         NV_ASSERT_OR_RETURN(pKernelGraphicsStaticInfo->pContextBuffersInfo != NULL, NV_ERR_INVALID_STATE);
3699     }
3700 
3701     size = pKernelGraphicsStaticInfo->pContextBuffersInfo->engine[engineId].size;
3702     alignment = pKernelGraphicsStaticInfo->pContextBuffersInfo->engine[engineId].alignment;
3703 
3704     if (size == NV_U32_MAX)
3705     {
3706         return NV_ERR_NOT_SUPPORTED;
3707     }
3708 
3709     if (pParams->bInfoPopulated)
3710     {
3711         size = NV_MAX(size, pParams->size);
3712         alignment = NV_MAX(alignment, pParams->alignment);
3713     }
3714 
3715     pParams->size = size;
3716     pParams->alignment = alignment;
3717     pParams->bInfoPopulated = NV_TRUE;
3718 
3719     return NV_OK;
3720 }
3721 
3722 /*!
3723  * @brief Gets the Graphics Context buffer size and alignment
3724  *
3725  *        Lock Requirements:
3726  *          Assert that API and Gpus lock held on entry
3727  */
3728 NV_STATUS
subdeviceCtrlCmdKGrGetCtxBufferSize_IMPL(Subdevice * pSubdevice,NV2080_CTRL_GR_GET_CTX_BUFFER_SIZE_PARAMS * pParams)3729 subdeviceCtrlCmdKGrGetCtxBufferSize_IMPL
3730 (
3731     Subdevice *pSubdevice,
3732     NV2080_CTRL_GR_GET_CTX_BUFFER_SIZE_PARAMS *pParams
3733 )
3734 {
3735     NV_STATUS status = NV_OK;
3736     OBJGPU *pGpu = GPU_RES_GET_GPU(pSubdevice);
3737     KernelGraphics *pKernelGraphics;
3738     RsClient *pClient = RES_GET_CLIENT(pSubdevice);
3739     Device *pDevice = GPU_RES_GET_DEVICE(pSubdevice);
3740     KernelGraphicsManager *pKernelGraphicsManager = GPU_GET_KERNEL_GRAPHICS_MANAGER(pGpu);
3741     NV2080_CTRL_GR_CTX_BUFFER_INFO *pCtxBufferInfo;
3742     NV2080_CTRL_GR_ROUTE_INFO grRouteInfo;
3743     KernelChannel *pKernelChannel;
3744     KernelGraphicsContext *pKernelGraphicsContext;
3745     NvU32 bufferCount;
3746     NvU64 totalBufferSize;
3747     NvU64 prevAlignment;
3748     NvU32 i;
3749 
3750     LOCK_ASSERT_AND_RETURN(rmapiLockIsOwner() && rmDeviceGpuLockIsOwner(pGpu->gpuInstance));
3751 
3752     //
3753     // vGPU:
3754     //
3755     // Since vGPU does all real hardware management in the
3756     // host, if we are in guest OS (where IS_VIRTUAL(pGpu) is true),
3757     // do an RPC to the host to fetch the total GR Context Buffer Size.
3758     //
3759     if (IS_VIRTUAL_WITHOUT_SRIOV(pGpu) ||
3760         (IS_VIRTUAL_WITH_SRIOV(pGpu) && gpuIsWarBug200577889SriovHeavyEnabled(pGpu)))
3761     {
3762         CALL_CONTEXT *pCallContext = resservGetTlsCallContext();
3763         RmCtrlParams *pRmCtrlParams = pCallContext->pControlParams;
3764 
3765         NV_RM_RPC_CONTROL(pGpu,
3766                           pRmCtrlParams->hClient,
3767                           pRmCtrlParams->hObject,
3768                           pRmCtrlParams->cmd,
3769                           pRmCtrlParams->pParams,
3770                           pRmCtrlParams->paramsSize,
3771                           status);
3772         return status;
3773     }
3774 
3775     portMemSet(&grRouteInfo, 0, sizeof(grRouteInfo));
3776     kgrmgrCtrlSetChannelHandle(pParams->hChannel, &grRouteInfo);
3777     NV_CHECK_OK_OR_RETURN(LEVEL_ERROR,
3778         kgrmgrCtrlRouteKGRWithDevice(pGpu, pKernelGraphicsManager, pDevice,
3779                                      &grRouteInfo, &pKernelGraphics));
3780 
3781     // Get channel from provided handle and owner client
3782     NV_CHECK_OK_OR_RETURN(LEVEL_INFO,
3783         CliGetKernelChannel(pClient, pParams->hChannel, &pKernelChannel));
3784 
3785     NV_CHECK_OK_OR_RETURN(LEVEL_ERROR,
3786         kgrctxFromKernelChannel(pKernelChannel, &pKernelGraphicsContext));
3787 
3788     // Get the total buffer count
3789     NV_CHECK_OK_OR_RETURN(LEVEL_ERROR,
3790         kgrctxGetBufferCount(pGpu, pKernelGraphicsContext, pKernelGraphics, &bufferCount));
3791 
3792     pCtxBufferInfo = portMemAllocNonPaged(bufferCount * sizeof(NV2080_CTRL_GR_CTX_BUFFER_INFO));
3793     NV_CHECK_OR_ELSE(LEVEL_ERROR,
3794                      pCtxBufferInfo != NULL,
3795                      status = NV_ERR_NO_MEMORY;
3796                      goto done;);
3797     portMemSet(pCtxBufferInfo, 0, bufferCount * sizeof(NV2080_CTRL_GR_CTX_BUFFER_INFO));
3798 
3799     NV_CHECK_OK_OR_GOTO(status, LEVEL_ERROR,
3800         kgrctxGetCtxBufferInfo(pGpu,
3801                                pKernelGraphicsContext,
3802                                pKernelGraphics,
3803                                kchannelGetGfid(pKernelChannel),
3804                                bufferCount,
3805                                &bufferCount,
3806                                pCtxBufferInfo),
3807         done);
3808 
3809     //
3810     // Calculate total size by walking thru all buffers & alignments. Adjust the total size
3811     // by adding the respective alignment so that the mapping VA can be adjusted.
3812     //
3813     totalBufferSize = 0;
3814     prevAlignment = 0x0;
3815     for (i = 0; i < bufferCount; i++)
3816     {
3817         if (prevAlignment != pCtxBufferInfo[i].alignment)
3818         {
3819             totalBufferSize += pCtxBufferInfo[i].alignment;
3820             prevAlignment = pCtxBufferInfo[i].alignment;
3821         }
3822 
3823         totalBufferSize += (pCtxBufferInfo[i].alignment != 0x0) ?
3824                 NV_ALIGN_UP(pCtxBufferInfo[i].size, pCtxBufferInfo[i].alignment) : pCtxBufferInfo[i].size;
3825     }
3826 
3827     pParams->totalBufferSize = totalBufferSize;
3828 
3829 done:
3830     portMemFree(pCtxBufferInfo);
3831     return status;
3832 }
3833 
3834 /*!
3835  * @brief Gets the Graphics Context buffer info like opaque buffer pointer
3836  *        size, alignment, aperture, allocation contiguity etc.
3837  *
3838  *        Lock Requirements:
3839  *          Assert that API and Gpus lock held on entry
3840  */
3841 NV_STATUS
subdeviceCtrlCmdKGrGetCtxBufferInfo_IMPL(Subdevice * pSubdevice,NV2080_CTRL_GR_GET_CTX_BUFFER_INFO_PARAMS * pParams)3842 subdeviceCtrlCmdKGrGetCtxBufferInfo_IMPL
3843 (
3844     Subdevice *pSubdevice,
3845     NV2080_CTRL_GR_GET_CTX_BUFFER_INFO_PARAMS *pParams
3846 )
3847 {
3848     NV_STATUS status = NV_OK;
3849     OBJGPU *pGpu = GPU_RES_GET_GPU(pSubdevice);
3850     KernelGraphicsManager *pKernelGraphicsManager = GPU_GET_KERNEL_GRAPHICS_MANAGER(pGpu);
3851     NV2080_CTRL_GR_ROUTE_INFO grRouteInfo;
3852     RsClient *pUserClient;
3853     KernelGraphics *pKernelGraphics;
3854     KernelChannel *pKernelChannel;
3855     KernelGraphicsContext *pKernelGraphicsContext;
3856 
3857     LOCK_ASSERT_AND_RETURN(rmapiLockIsOwner() && rmGpuLockIsOwner());
3858 
3859     //
3860     // vGPU:
3861     //
3862     // Since vGPU does all real hardware management in the
3863     // host, if we are in guest OS (where IS_VIRTUAL(pGpu) is true),
3864     // do an RPC to the host to get Graphics context buffers information.
3865     //
3866     if (IS_VIRTUAL_WITHOUT_SRIOV(pGpu) ||
3867         (IS_VIRTUAL_WITH_SRIOV(pGpu) && gpuIsWarBug200577889SriovHeavyEnabled(pGpu)))
3868     {
3869         CALL_CONTEXT *pCallContext = resservGetTlsCallContext();
3870         RmCtrlParams *pRmCtrlParams = pCallContext->pControlParams;
3871 
3872         NV_RM_RPC_CONTROL(pGpu,
3873                           pRmCtrlParams->hClient,
3874                           pRmCtrlParams->hObject,
3875                           pRmCtrlParams->cmd,
3876                           pRmCtrlParams->pParams,
3877                           pRmCtrlParams->paramsSize,
3878                           status);
3879         return status;
3880     }
3881 
3882     NV_CHECK_OK_OR_RETURN(LEVEL_INFO,
3883         serverGetClientUnderLock(&g_resServ, pParams->hUserClient, &pUserClient));
3884 
3885     // Get channel from provided handle and owner client
3886     NV_CHECK_OK_OR_RETURN(LEVEL_INFO,
3887         CliGetKernelChannel(pUserClient, pParams->hChannel, &pKernelChannel));
3888 
3889     portMemSet(&grRouteInfo, 0, sizeof(grRouteInfo));
3890     kgrmgrCtrlSetChannelHandle(pParams->hChannel, &grRouteInfo);
3891     NV_CHECK_OK_OR_RETURN(LEVEL_ERROR,
3892         kgrmgrCtrlRouteKGRWithDevice(pGpu, pKernelGraphicsManager,
3893                                      GPU_RES_GET_DEVICE(pKernelChannel),
3894                                      &grRouteInfo, &pKernelGraphics));
3895 
3896     NV_CHECK_OK_OR_RETURN(LEVEL_ERROR,
3897         kgrctxFromKernelChannel(pKernelChannel, &pKernelGraphicsContext));
3898 
3899     NV_CHECK_OK_OR_RETURN(LEVEL_ERROR,
3900         kgrctxGetCtxBufferInfo(pGpu,
3901                                pKernelGraphicsContext,
3902                                pKernelGraphics,
3903                                kchannelGetGfid(pKernelChannel),
3904                                NV_ARRAY_ELEMENTS(pParams->ctxBufferInfo),
3905                                &pParams->bufferCount,
3906                                pParams->ctxBufferInfo));
3907 
3908     return status;
3909 }
3910 
3911 /*!
3912  * subdeviceCtrlCmdKGrInternalGetCtxBufferPtes
3913  *
3914  * Lock Requirements:
3915  *      Assert that API lock and GPUs lock held on entry
3916  */
3917 NV_STATUS
subdeviceCtrlCmdKGrGetCtxBufferPtes_IMPL(Subdevice * pSubdevice,NV2080_CTRL_KGR_GET_CTX_BUFFER_PTES_PARAMS * pParams)3918 subdeviceCtrlCmdKGrGetCtxBufferPtes_IMPL
3919 (
3920     Subdevice *pSubdevice,
3921     NV2080_CTRL_KGR_GET_CTX_BUFFER_PTES_PARAMS *pParams
3922 )
3923 {
3924     NV_STATUS status = NV_OK;
3925     OBJGPU *pGpu = GPU_RES_GET_GPU(pSubdevice);
3926     KernelGraphicsManager *pKernelGraphicsManager = GPU_GET_KERNEL_GRAPHICS_MANAGER(pGpu);
3927     NV2080_CTRL_GR_ROUTE_INFO grRouteInfo;
3928     RsClient *pUserClient;
3929     KernelGraphics *pKernelGraphics;
3930     KernelChannel *pKernelChannel;
3931     KernelGraphicsContext *pKernelGraphicsContext;
3932 
3933     LOCK_ASSERT_AND_RETURN(rmapiLockIsOwner() && rmGpuLockIsOwner());
3934 
3935     //
3936     // Currently, ROUTE_TO_VGPU_HOST instructs resource server to call the RPC
3937     // on all vGPU configurations including SRIOV Standard which is not required.
3938     // Hence, manually dispatching the RPC for required vGPU configs.
3939     //
3940     // vGPU:
3941     //
3942     // Since vGPU does all real hardware management in the
3943     // host, if we are in guest OS (where IS_VIRTUAL(pGpu) is true),
3944     // do an RPC to the host to get Graphics context buffers PTEs information.
3945     //
3946     if (IS_VIRTUAL_WITHOUT_SRIOV(pGpu) ||
3947         (IS_VIRTUAL_WITH_SRIOV(pGpu) && gpuIsWarBug200577889SriovHeavyEnabled(pGpu)))
3948     {
3949         CALL_CONTEXT *pCallContext = resservGetTlsCallContext();
3950         RmCtrlParams *pRmCtrlParams = pCallContext->pControlParams;
3951         NvHandle hClient = RES_GET_CLIENT_HANDLE(pSubdevice);
3952         NvHandle hObject = RES_GET_HANDLE(pSubdevice);
3953 
3954         NV_RM_RPC_CONTROL(pGpu,
3955                           hClient,
3956                           hObject,
3957                           pRmCtrlParams->cmd,
3958                           pRmCtrlParams->pParams,
3959                           pRmCtrlParams->paramsSize,
3960                           status);
3961         return status;
3962     }
3963 
3964     NV_CHECK_OK_OR_RETURN(LEVEL_INFO,
3965         serverGetClientUnderLock(&g_resServ, pParams->hUserClient, &pUserClient));
3966 
3967     // Get channel from provided handle and owner client
3968     NV_CHECK_OK_OR_RETURN(LEVEL_INFO,
3969         CliGetKernelChannel(pUserClient, pParams->hChannel, &pKernelChannel));
3970 
3971     portMemSet(&grRouteInfo, 0, sizeof(grRouteInfo));
3972     kgrmgrCtrlSetChannelHandle(pParams->hChannel, &grRouteInfo);
3973     NV_CHECK_OK_OR_RETURN(LEVEL_INFO,
3974         kgrmgrCtrlRouteKGRWithDevice(pGpu, pKernelGraphicsManager,
3975                                      GPU_RES_GET_DEVICE(pKernelChannel),
3976                                      &grRouteInfo, &pKernelGraphics));
3977 
3978     NV_CHECK_OK_OR_RETURN(LEVEL_ERROR,
3979         kgrctxFromKernelChannel(pKernelChannel, &pKernelGraphicsContext));
3980 
3981     NV_CHECK_OK_OR_RETURN(LEVEL_ERROR,
3982         kgrctxGetCtxBufferPtes(pGpu,
3983                                pKernelGraphicsContext,
3984                                pKernelGraphics,
3985                                kchannelGetGfid(pKernelChannel),
3986                                pParams->bufferType,
3987                                pParams->firstPage,
3988                                pParams->physAddrs,
3989                                NV_ARRAY_ELEMENTS(pParams->physAddrs),
3990                                &pParams->numPages,
3991                                &pParams->bNoMorePages));
3992 
3993     return status;
3994 }
3995 
3996 /*!
3997  * subdeviceCtrlCmdKGrGetGfxGpcAndTpcInfo
3998  *
3999  * Lock Requirements:
4000  *      Assert that API lock and GPUs lock held on entry
4001  */
4002 NV_STATUS
subdeviceCtrlCmdKGrGetGfxGpcAndTpcInfo_IMPL(Subdevice * pSubdevice,NV2080_CTRL_GR_GET_GFX_GPC_AND_TPC_INFO_PARAMS * pParams)4003 subdeviceCtrlCmdKGrGetGfxGpcAndTpcInfo_IMPL
4004 (
4005     Subdevice *pSubdevice,
4006     NV2080_CTRL_GR_GET_GFX_GPC_AND_TPC_INFO_PARAMS *pParams
4007 )
4008 {
4009     OBJGPU *pGpu = GPU_RES_GET_GPU(pSubdevice);
4010     KernelGraphicsManager *pKernelGraphicsManager = GPU_GET_KERNEL_GRAPHICS_MANAGER(pGpu);
4011     KernelGraphics *pKernelGraphics;
4012     const KGRAPHICS_STATIC_INFO *pKernelGraphicsStaticInfo;
4013     Device *pDevice = GPU_RES_GET_DEVICE(pSubdevice);
4014 
4015     LOCK_ASSERT_AND_RETURN(rmapiLockIsOwner() && rmGpuLockIsOwner());
4016 
4017     NV_CHECK_OK_OR_RETURN(LEVEL_ERROR,
4018         kgrmgrCtrlRouteKGRWithDevice(pGpu, pKernelGraphicsManager, pDevice,
4019                                      &pParams->grRouteInfo, &pKernelGraphics));
4020 
4021     // Verify static info is available
4022     pKernelGraphicsStaticInfo = kgraphicsGetStaticInfo(pGpu, pKernelGraphics);
4023     NV_ASSERT_OR_RETURN(pKernelGraphicsStaticInfo != NULL, NV_ERR_INVALID_STATE);
4024 
4025     pParams->physGfxGpcMask = pKernelGraphicsStaticInfo->floorsweepingMasks.physGfxGpcMask;
4026     pParams->numGfxTpc = pKernelGraphicsStaticInfo->floorsweepingMasks.numGfxTpc;
4027 
4028     return NV_OK;
4029 }
4030 
4031 #define KGR_DO_WITH_GR(pGpu, pKernelGraphics, body) do                                            \
4032     {                                                                                             \
4033         (body);                                                                                   \
4034     } while (0);
4035 
4036 NV_STATUS
subdeviceCtrlCmdGrInternalSetFecsTraceHwEnable_IMPL(Subdevice * pSubdevice,NV2080_CTRL_INTERNAL_GR_SET_FECS_TRACE_HW_ENABLE_PARAMS * pParams)4037 subdeviceCtrlCmdGrInternalSetFecsTraceHwEnable_IMPL
4038 (
4039     Subdevice *pSubdevice,
4040     NV2080_CTRL_INTERNAL_GR_SET_FECS_TRACE_HW_ENABLE_PARAMS *pParams
4041 )
4042 {
4043     OBJGPU *pGpu = GPU_RES_GET_GPU(pSubdevice);
4044     KernelGraphicsManager *pKernelGraphicsManager = GPU_GET_KERNEL_GRAPHICS_MANAGER(pGpu);
4045     Device *pDevice = GPU_RES_GET_DEVICE(pSubdevice);
4046     NV_STATUS status = NV_OK;
4047     KernelGraphics *pKernelGraphics;
4048 
4049     LOCK_ASSERT_AND_RETURN(rmDeviceGpuLockIsOwner(pGpu->gpuInstance));
4050 
4051     NV_CHECK_OK_OR_RETURN(
4052         LEVEL_ERROR,
4053         kgrmgrCtrlRouteKGRWithDevice(pGpu, pKernelGraphicsManager, pDevice,
4054                                      &pParams->grRouteInfo, &pKernelGraphics));
4055 
4056     KGR_DO_WITH_GR(pGpu, pKernelGraphics,
4057                    kgraphicsSetFecsTraceHwEnable_HAL(pGpu, pKernelGraphics, pParams->bEnable));
4058     pKernelGraphics->bCtxswLoggingEnabled = pParams->bEnable;
4059 
4060     return status;
4061 }
4062 
4063 NV_STATUS
subdeviceCtrlCmdGrInternalGetFecsTraceHwEnable_IMPL(Subdevice * pSubdevice,NV2080_CTRL_INTERNAL_GR_GET_FECS_TRACE_HW_ENABLE_PARAMS * pParams)4064 subdeviceCtrlCmdGrInternalGetFecsTraceHwEnable_IMPL
4065 (
4066     Subdevice *pSubdevice,
4067     NV2080_CTRL_INTERNAL_GR_GET_FECS_TRACE_HW_ENABLE_PARAMS *pParams
4068 )
4069 {
4070     OBJGPU *pGpu = GPU_RES_GET_GPU(pSubdevice);
4071     KernelGraphicsManager *pKernelGraphicsManager = GPU_GET_KERNEL_GRAPHICS_MANAGER(pGpu);
4072     Device *pDevice = GPU_RES_GET_DEVICE(pSubdevice);
4073     NV_STATUS status = NV_OK;
4074     KernelGraphics *pKernelGraphics;
4075 
4076     LOCK_ASSERT_AND_RETURN(rmDeviceGpuLockIsOwner(pGpu->gpuInstance));
4077 
4078     NV_CHECK_OK_OR_RETURN(
4079         LEVEL_ERROR,
4080         kgrmgrCtrlRouteKGRWithDevice(pGpu, pKernelGraphicsManager, pDevice, &pParams->grRouteInfo,
4081                                      &pKernelGraphics));
4082 
4083     KGR_DO_WITH_GR(pGpu, pKernelGraphics,
4084                    pParams->bEnable = kgraphicsIsCtxswLoggingEnabled(pGpu, pKernelGraphics));
4085 
4086     return status;
4087 }
4088 
4089 NV_STATUS
subdeviceCtrlCmdGrInternalSetFecsTraceRdOffset_IMPL(Subdevice * pSubdevice,NV2080_CTRL_INTERNAL_GR_SET_FECS_TRACE_RD_OFFSET_PARAMS * pParams)4090 subdeviceCtrlCmdGrInternalSetFecsTraceRdOffset_IMPL
4091 (
4092     Subdevice *pSubdevice,
4093     NV2080_CTRL_INTERNAL_GR_SET_FECS_TRACE_RD_OFFSET_PARAMS *pParams
4094 )
4095 {
4096     OBJGPU *pGpu = GPU_RES_GET_GPU(pSubdevice);
4097     KernelGraphicsManager *pKernelGraphicsManager = GPU_GET_KERNEL_GRAPHICS_MANAGER(pGpu);
4098     Device *pDevice = GPU_RES_GET_DEVICE(pSubdevice);
4099     NV_STATUS status = NV_OK;
4100     KernelGraphics *pKernelGraphics;
4101 
4102     LOCK_ASSERT_AND_RETURN(rmDeviceGpuLockIsOwner(pGpu->gpuInstance));
4103 
4104     NV_CHECK_OK_OR_RETURN(
4105         LEVEL_ERROR,
4106         kgrmgrCtrlRouteKGRWithDevice(pGpu, pKernelGraphicsManager, pDevice, &pParams->grRouteInfo,
4107                                      &pKernelGraphics));
4108 
4109     KGR_DO_WITH_GR(pGpu, pKernelGraphics,
4110                    kgraphicsSetFecsTraceRdOffset_HAL(pGpu, pKernelGraphics, pParams->offset));
4111 
4112     return status;
4113 }
4114 
4115 NV_STATUS
subdeviceCtrlCmdGrInternalGetFecsTraceRdOffset_IMPL(Subdevice * pSubdevice,NV2080_CTRL_INTERNAL_GR_GET_FECS_TRACE_RD_OFFSET_PARAMS * pParams)4116 subdeviceCtrlCmdGrInternalGetFecsTraceRdOffset_IMPL
4117 (
4118     Subdevice *pSubdevice,
4119     NV2080_CTRL_INTERNAL_GR_GET_FECS_TRACE_RD_OFFSET_PARAMS *pParams
4120 )
4121 {
4122     OBJGPU *pGpu = GPU_RES_GET_GPU(pSubdevice);
4123     KernelGraphicsManager *pKernelGraphicsManager = GPU_GET_KERNEL_GRAPHICS_MANAGER(pGpu);
4124     Device *pDevice = GPU_RES_GET_DEVICE(pSubdevice);
4125     NV_STATUS status = NV_OK;
4126     KernelGraphics *pKernelGraphics;
4127 
4128     LOCK_ASSERT_AND_RETURN(rmDeviceGpuLockIsOwner(pGpu->gpuInstance));
4129 
4130     NV_CHECK_OK_OR_RETURN(
4131         LEVEL_ERROR,
4132         kgrmgrCtrlRouteKGRWithDevice(pGpu, pKernelGraphicsManager, pDevice, &pParams->grRouteInfo,
4133                                      &pKernelGraphics));
4134 
4135     KGR_DO_WITH_GR(pGpu, pKernelGraphics,
4136                    pParams->offset = kgraphicsGetFecsTraceRdOffset_HAL(pGpu, pKernelGraphics));
4137 
4138     return status;
4139 }
4140 
4141 NV_STATUS
subdeviceCtrlCmdGrInternalSetFecsTraceWrOffset_IMPL(Subdevice * pSubdevice,NV2080_CTRL_INTERNAL_GR_SET_FECS_TRACE_WR_OFFSET_PARAMS * pParams)4142 subdeviceCtrlCmdGrInternalSetFecsTraceWrOffset_IMPL
4143 (
4144     Subdevice *pSubdevice,
4145     NV2080_CTRL_INTERNAL_GR_SET_FECS_TRACE_WR_OFFSET_PARAMS *pParams
4146 )
4147 {
4148     OBJGPU *pGpu = GPU_RES_GET_GPU(pSubdevice);
4149     KernelGraphicsManager *pKernelGraphicsManager = GPU_GET_KERNEL_GRAPHICS_MANAGER(pGpu);
4150     Device *pDevice = GPU_RES_GET_DEVICE(pSubdevice);
4151     NV_STATUS status = NV_OK;
4152     KernelGraphics *pKernelGraphics;
4153 
4154     LOCK_ASSERT_AND_RETURN(rmDeviceGpuLockIsOwner(pGpu->gpuInstance));
4155 
4156     NV_CHECK_OK_OR_RETURN(
4157         LEVEL_ERROR,
4158         kgrmgrCtrlRouteKGRWithDevice(pGpu, pKernelGraphicsManager, pDevice, &pParams->grRouteInfo,
4159                                      &pKernelGraphics));
4160 
4161     KGR_DO_WITH_GR(pGpu, pKernelGraphics,
4162                    kgraphicsSetFecsTraceWrOffset_HAL(pGpu, pKernelGraphics, pParams->offset));
4163 
4164     return status;
4165 }
4166