1 /*
2  * SPDX-FileCopyrightText: Copyright (c) 2021-2024 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 /*!
25  * @file  kern_gmmu_tu102.c
26  * @brief TURING specific HAL MMU routines reside in this file
27  */
28 
29 #include "nvtypes.h"
30 #define NVOC_KERN_GMMU_H_PRIVATE_ACCESS_ALLOWED
31 
32 #include "gpu/mmu/kern_gmmu.h"
33 #include "gpu/gpu.h"
34 #include "kernel/gpu/intr/intr.h"
35 #include "gpu/mem_sys/kern_mem_sys.h"
36 
37 #include "published/turing/tu102/dev_fault.h"
38 #include "published/turing/tu102/dev_fb.h"
39 #include "published/turing/tu102/dev_vm.h"
40 
41 
42 /*!
43  * @brief Checks for any pending invalidations.
44  *
45  * @param pGpu
46  * @param pKernelGmmu
47  * @param pTimeOut      Timeout for the invalidate operation.
48  * @param gfid          GFID
49  */
50 NV_STATUS
kgmmuCheckPendingInvalidates_TU102(OBJGPU * pGpu,KernelGmmu * pKernelGmmu,RMTIMEOUT * pTimeOut,NvU32 gfid)51 kgmmuCheckPendingInvalidates_TU102
52 (
53     OBJGPU     *pGpu,
54     KernelGmmu *pKernelGmmu,
55     RMTIMEOUT  *pTimeOut,
56     NvU32       gfid
57 )
58 {
59     NV_STATUS status = NV_OK;
60 
61     while (1)
62     {
63         NvU32   regVal;
64 
65         {
66             NV_ASSERT(IS_GFID_PF(gfid));
67 
68             regVal = GPU_VREG_RD32(pGpu, NV_VIRTUAL_FUNCTION_PRIV_MMU_INVALIDATE);
69         }
70 
71         if (FLD_TEST_DRF(_VIRTUAL_FUNCTION_PRIV, _MMU_INVALIDATE, _TRIGGER, _FALSE, regVal))
72             break;
73 
74         if (API_GPU_IN_RESET_SANITY_CHECK(pGpu))
75             status = NV_ERR_GPU_IN_FULLCHIP_RESET;
76         else if (!API_GPU_ATTACHED_SANITY_CHECK(pGpu))
77             status = NV_ERR_GPU_IS_LOST;
78         else
79             status = gpuCheckTimeout(pGpu, pTimeOut);
80 
81         if (NV_OK != status)
82             break;
83 
84         osSpinLoop();
85     }
86     return status;
87 }
88 
89 /*!
90  * @brief Commit the invalidate command to H/W.
91  *
92  * @param pGpu
93  * @param pKernelGmmu
94  * @param pParams      Pointer to TLB_INVALIDATE_PARAMS data.
95  */
96 NV_STATUS
kgmmuCommitTlbInvalidate_TU102(OBJGPU * pGpu,KernelGmmu * pKernelGmmu,TLB_INVALIDATE_PARAMS * pParams)97 kgmmuCommitTlbInvalidate_TU102
98 (
99     OBJGPU                *pGpu,
100     KernelGmmu            *pKernelGmmu,
101     TLB_INVALIDATE_PARAMS *pParams
102 )
103 {
104     NV_STATUS status = NV_OK;
105 
106     if (!FLD_TEST_DRF(_VIRTUAL_FUNCTION_PRIV, _MMU_INVALIDATE, _ALL_PDB, _TRUE, pParams->regVal))
107     {
108         kgmmuSetPdbToInvalidate_HAL(pGpu, pKernelGmmu, pParams);
109     }
110 
111     {
112         NV_ASSERT(IS_GFID_PF(pParams->gfid));
113 
114         if (IS_VIRTUAL(pGpu))
115         {
116             // Prevent VF from updating INVALIDATE_ALL_PDB, bug 3356599
117             pParams->regVal = FLD_SET_DRF(_VIRTUAL_FUNCTION_PRIV, _MMU_INVALIDATE, _ALL_PDB, _FALSE, pParams->regVal);
118         }
119 
120         GPU_VREG_WR32(pGpu, NV_VIRTUAL_FUNCTION_PRIV_MMU_INVALIDATE, pParams->regVal);
121     }
122 
123     // Wait for the invalidate command to complete.
124     status = kgmmuCheckPendingInvalidates_HAL(pGpu, pKernelGmmu, &pParams->timeout, pParams->gfid);
125 
126     return status;
127 }
128 
129 /*!
130  * @brief This function sets the PDB physical address for the VAS whose
131  *        entries are to be invalidated.
132  *
133  * @param[in] pGpu
134  * @param[in] pKernelGmmu
135  * @param[in] pParams       Pointer to TLB_INVALIDATE_PARAMS data
136  */
137 void
kgmmuSetPdbToInvalidate_TU102(OBJGPU * pGpu,KernelGmmu * pKernelGmmu,TLB_INVALIDATE_PARAMS * pParams)138 kgmmuSetPdbToInvalidate_TU102
139 (
140     OBJGPU                *pGpu,
141     KernelGmmu            *pKernelGmmu,
142     TLB_INVALIDATE_PARAMS *pParams
143 )
144 {
145     {
146         NV_ASSERT(IS_GFID_PF(pParams->gfid));
147 
148         GPU_VREG_WR32(pGpu, NV_VIRTUAL_FUNCTION_PRIV_MMU_INVALIDATE_PDB,
149                 DRF_NUM(_VIRTUAL_FUNCTION_PRIV, _MMU_INVALIDATE_PDB, _ADDR,
150                         NvU64_LO32(pParams->pdbAddress >>
151                                 NV_VIRTUAL_FUNCTION_PRIV_MMU_INVALIDATE_PDB_ADDR_ALIGNMENT)) |
152                 DRF_NUM(_VIRTUAL_FUNCTION_PRIV, _MMU_INVALIDATE_PDB, _APERTURE, pParams->pdbAperture));
153 
154         GPU_VREG_WR32(pGpu, NV_VIRTUAL_FUNCTION_PRIV_MMU_INVALIDATE_UPPER_PDB,
155                 DRF_NUM(_VIRTUAL_FUNCTION_PRIV, _MMU_INVALIDATE_UPPER_PDB, _ADDR,
156                         NvU64_LO32((pParams->pdbAddress >>
157                                     NV_VIRTUAL_FUNCTION_PRIV_MMU_INVALIDATE_PDB_ADDR_ALIGNMENT) >>
158                                     DRF_SIZE(NV_VIRTUAL_FUNCTION_PRIV_MMU_INVALIDATE_PDB_ADDR))));
159     }
160 }
161 
162 /*!
163  * @brief Set membar parameters for tlb invalidation and return
164  * any additional sysmembar flushes that is required after tlb invalidation
165  * is committed.
166  *
167  * During PTE downgrades, tlb invalidates should be followed by
168  * sysmembar. Since Turing doesnt have HSHUB we dont need any
169  * additional flushes.
170  *
171  * Use invalidate units SYSMEMBAR and return flushCount 0.
172  *
173  * @param[in] pGpu
174  * @param[in] pKernelGmmu
175  * @param[in] pParams     Tlb invalidation parameter structure.
176  *
177  */
178 NvU32
kgmmuSetTlbInvalidateMembarWarParameters_TU102(OBJGPU * pGpu,KernelGmmu * pKernelGmmu,TLB_INVALIDATE_PARAMS * pParams)179 kgmmuSetTlbInvalidateMembarWarParameters_TU102
180 (
181     OBJGPU                *pGpu,
182     KernelGmmu            *pKernelGmmu,
183     TLB_INVALIDATE_PARAMS *pParams
184 )
185 {
186 
187     pParams->regVal = FLD_SET_DRF(_VIRTUAL_FUNCTION_PRIV, _MMU_INVALIDATE, _SYS_MEMBAR, _TRUE, pParams->regVal);
188     pParams->regVal = FLD_SET_DRF(_VIRTUAL_FUNCTION_PRIV, _MMU_INVALIDATE, _ACK,    _GLOBALLY, pParams->regVal);
189 
190     return 0;
191 }
192 
193 NV_STATUS
kgmmuGetFaultRegisterMappings_TU102(OBJGPU * pGpu,KernelGmmu * pKernelGmmu,NvU32 index,NvP64 * pFaultBufferGet,NvP64 * pFaultBufferPut,NvP64 * pFaultBufferInfo,NvP64 * pHubIntr,NvP64 * pHubIntrEnSet,NvP64 * pHubIntrEnClear,NvU32 * faultMask,NvP64 * pPrefetchCtrl)194 kgmmuGetFaultRegisterMappings_TU102
195 (
196     OBJGPU               *pGpu,
197     KernelGmmu            *pKernelGmmu,
198     NvU32                 index,
199     NvP64                 *pFaultBufferGet,
200     NvP64                 *pFaultBufferPut,
201     NvP64                 *pFaultBufferInfo,
202     NvP64                 *pHubIntr,
203     NvP64                 *pHubIntrEnSet,
204     NvP64                 *pHubIntrEnClear,
205     NvU32                 *faultMask,
206     NvP64                 *pPrefetchCtrl
207 )
208 {
209     Intr               *pIntr       = GPU_GET_INTR(pGpu);
210     DEVICE_MAPPING     *pMapping    = gpuGetDeviceMapping(pGpu, DEVICE_INDEX_GPU, 0);
211     NvP64               bar0Mapping = NV_PTR_TO_NvP64(pMapping->gpuNvAddr);
212     NvU32               intrVector  = intrGetVectorFromEngineId(pGpu, pIntr, MC_ENGINE_IDX_REPLAYABLE_FAULT, NV_FALSE);
213     NvU32 leafReg, leafBit;
214 
215     leafReg = NV_CTRL_INTR_GPU_VECTOR_TO_LEAF_REG(intrVector);
216     leafBit = NV_CTRL_INTR_GPU_VECTOR_TO_LEAF_BIT(intrVector);
217 
218     NV_ASSERT_OR_RETURN((index < NUM_FAULT_BUFFERS), NV_ERR_INVALID_ARGUMENT);
219 
220     *pFaultBufferGet = NvP64_PLUS_OFFSET(bar0Mapping,
221                  GPU_GET_VREG_OFFSET(pGpu, NV_VIRTUAL_FUNCTION_PRIV_MMU_FAULT_BUFFER_GET(index)));
222     *pFaultBufferPut = NvP64_PLUS_OFFSET(bar0Mapping,
223                  GPU_GET_VREG_OFFSET(pGpu, NV_VIRTUAL_FUNCTION_PRIV_MMU_FAULT_BUFFER_PUT(index)));
224     // Note: this variable is deprecated since buffer overflow is not a seperate register from Volta
225     *pFaultBufferInfo = 0;
226     *pHubIntr = NvP64_PLUS_OFFSET(bar0Mapping, GPU_GET_VREG_OFFSET(pGpu, NV_VIRTUAL_FUNCTION_PRIV_CPU_INTR_LEAF(leafReg)));
227     *pHubIntrEnSet = NvP64_PLUS_OFFSET(bar0Mapping, GPU_GET_VREG_OFFSET(pGpu, NV_VIRTUAL_FUNCTION_PRIV_CPU_INTR_LEAF_EN_SET(leafReg)));
228     *pHubIntrEnClear = NvP64_PLUS_OFFSET(bar0Mapping, GPU_GET_VREG_OFFSET(pGpu, NV_VIRTUAL_FUNCTION_PRIV_CPU_INTR_LEAF_EN_CLEAR(leafReg)));
229 
230     // Only REPLAYABLE fault buffer and ACCESS Counter interrupts can be owned by clients
231     if (index == NV_VIRTUAL_FUNCTION_PRIV_MMU_REPLAY_FAULT_BUFFER)
232     {
233         *faultMask = NVBIT(leafBit);
234         *pPrefetchCtrl = NvP64_PLUS_OFFSET(bar0Mapping, GPU_GET_VREG_OFFSET(pGpu, NV_VIRTUAL_FUNCTION_PRIV_MMU_PAGE_FAULT_CTRL));
235     }
236 
237     return NV_OK;
238 }
239 
240 
241 /**
242  * @brief Test the access counter write NAK.
243  *
244  * @param[in]  pGpu
245  * @param[in]  pKernelGmmu
246  * @retval     true                  Write was negatively acknowledged.
247  */
kgmmuTestAccessCounterWriteNak_TU102(OBJGPU * pGpu,KernelGmmu * pKernelGmmu)248 NvBool kgmmuTestAccessCounterWriteNak_TU102
249 (
250     OBJGPU     *pGpu,
251     KernelGmmu *pKernelGmmu
252 )
253 {
254     NvU32 accessCntrInfo = GPU_VREG_RD32(pGpu, NV_VIRTUAL_FUNCTION_PRIV_ACCESS_COUNTER_NOTIFY_BUFFER_INFO);
255     return FLD_TEST_DRF(_VIRTUAL_FUNCTION_PRIV, _ACCESS_COUNTER_NOTIFY_BUFFER_INFO,
256                                       _WRITE_NACK, _TRUE, accessCntrInfo);
257 }
258 
259 /*!
260  * @brief Service replayable fault
261  *
262  * @param[in] pGpu
263  * @param[in] pKernelGmmu
264  *
265  * @returns NV_STATUS
266  */
267 NV_STATUS
kgmmuServiceReplayableFault_TU102(OBJGPU * pGpu,KernelGmmu * pKernelGmmu)268 kgmmuServiceReplayableFault_TU102
269 (
270     OBJGPU     *pGpu,
271     KernelGmmu *pKernelGmmu
272 )
273 {
274     NV_STATUS rmStatus = NV_OK;
275     PEVENTNOTIFICATION *ppEventNotification  = NULL;
276 
277     if (IS_VIRTUAL_WITHOUT_SRIOV(pGpu))
278         return NV_OK;
279 
280     if (NV_OK == CliGetEventNotificationList(pKernelGmmu->mmuFaultBuffer[GPU_GFID_PF].hFaultBufferClient,
281           pKernelGmmu->mmuFaultBuffer[GPU_GFID_PF].hFaultBufferObject, NULL, &ppEventNotification) && ppEventNotification)
282     {
283         rmStatus = notifyEvents(pGpu, *ppEventNotification, NVC369_NOTIFIER_MMU_FAULT_REPLAYABLE,
284                                 0, 0, NV_OK, NV_OS_WRITE_THEN_AWAKEN);
285         NV_ASSERT(rmStatus == NV_OK);
286     }
287     return rmStatus;
288 }
289 
290 NvU32
kgmmuReadMmuFaultStatus_TU102(OBJGPU * pGpu,KernelGmmu * pKernelGmmu,NvU32 gfid)291 kgmmuReadMmuFaultStatus_TU102
292 (
293     OBJGPU     *pGpu,
294     KernelGmmu *pKernelGmmu,
295     NvU32       gfid
296 )
297 {
298     {
299         NV_ASSERT(IS_GFID_PF(gfid));
300 
301         return GPU_VREG_RD32(pGpu, NV_VIRTUAL_FUNCTION_PRIV_MMU_FAULT_STATUS);
302     }
303 }
304 
305 void
kgmmuWriteMmuFaultStatus_TU102(OBJGPU * pGpu,KernelGmmu * pKernelGmmu,NvU32 value)306 kgmmuWriteMmuFaultStatus_TU102
307 (
308     OBJGPU     *pGpu,
309     KernelGmmu *pKernelGmmu,
310     NvU32       value
311 )
312 {
313     GPU_VREG_WR32(pGpu, NV_VIRTUAL_FUNCTION_PRIV_MMU_FAULT_STATUS, value);
314 }
315 
316 NvU32
kgmmuReadMmuFaultBufferSize_TU102(OBJGPU * pGpu,KernelGmmu * pKernelGmmu,NvU32 index,NvU32 gfid)317 kgmmuReadMmuFaultBufferSize_TU102
318 (
319     OBJGPU     *pGpu,
320     KernelGmmu *pKernelGmmu,
321     NvU32       index,
322     NvU32       gfid
323 )
324 {
325     {
326         NV_ASSERT(IS_GFID_PF(gfid));
327 
328         return GPU_VREG_RD32(pGpu, NV_VIRTUAL_FUNCTION_PRIV_MMU_FAULT_BUFFER_SIZE(index));
329     }
330 }
331 
332 NV_STATUS
kgmmuReadFaultBufferGetPtr_TU102(OBJGPU * pGpu,KernelGmmu * pKernelGmmu,NvU32 index,NvU32 * pGetOffset,THREAD_STATE_NODE * pThreadState)333 kgmmuReadFaultBufferGetPtr_TU102
334 (
335     OBJGPU               *pGpu,
336     KernelGmmu           *pKernelGmmu,
337     NvU32                 index,
338     NvU32                *pGetOffset,
339     THREAD_STATE_NODE    *pThreadState
340 )
341 {
342     NvU32 val;
343     NV_ASSERT_OR_RETURN((index < NUM_FAULT_BUFFERS), NV_ERR_INVALID_ARGUMENT);
344 
345     val = GPU_VREG_RD32_EX(pGpu, NV_VIRTUAL_FUNCTION_PRIV_MMU_FAULT_BUFFER_GET(index), pThreadState);
346     *pGetOffset = DRF_VAL(_VIRTUAL_FUNCTION_PRIV, _MMU_FAULT_BUFFER_GET, _PTR, val);
347 
348     return NV_OK;
349 }
350 
351 NV_STATUS
kgmmuWriteFaultBufferGetPtr_TU102(OBJGPU * pGpu,KernelGmmu * pKernelGmmu,NvU32 index,NvU32 getValue,THREAD_STATE_NODE * pThreadState)352 kgmmuWriteFaultBufferGetPtr_TU102
353 (
354     OBJGPU               *pGpu,
355     KernelGmmu           *pKernelGmmu,
356     NvU32                 index,
357     NvU32                 getValue,
358     THREAD_STATE_NODE    *pThreadState
359 )
360 {
361     NV_ASSERT_OR_RETURN((index < NUM_FAULT_BUFFERS), NV_ERR_INVALID_ARGUMENT);
362 
363     if (index == REPLAYABLE_FAULT_BUFFER)
364     {
365         //
366         // If HW has detected an overflow condition (PUT == GET - 1 and a fault has
367         // arrived, which is dropped due to no more space in the fault buffer), it will
368         // not deliver any more faults into the buffer until the overflow condition has
369         // been cleared. The overflow condition is cleared by updating the GET index to
370         // indicate space in the buffer and writing 1 to the OVERFLOW bit in GET.
371         // Unfortunately, this can not be done in the same write because it can collide
372         // with an arriving fault on the same cycle, resulting in the overflow condition
373         // being instantly reasserted.
374         // However, if the index is updated first and then the OVERFLOW bit is cleared
375         // such a collision will not cause a reassertion of the overflow condition.
376         //
377         GPU_VREG_WR32_EX(pGpu, NV_VIRTUAL_FUNCTION_PRIV_MMU_FAULT_BUFFER_GET(index), getValue, pThreadState);
378         getValue = FLD_SET_DRF(_VIRTUAL_FUNCTION_PRIV, _MMU_FAULT_BUFFER_GET, _OVERFLOW, _CLEAR, getValue);
379         getValue = FLD_SET_DRF(_VIRTUAL_FUNCTION_PRIV, _MMU_FAULT_BUFFER_GET, _GETPTR_CORRUPTED, _CLEAR, getValue);
380     }
381     else
382     {
383         //
384         // Mask off the _OVERFLOW and _GETPTR_CORRUPTED bits. Writing 0 should
385         // have no effect, but they're write 1 to clear so make sure we're not
386         // trying to clear an overflow or the corrupted bit.
387         //
388         getValue = FLD_SET_DRF(_VIRTUAL_FUNCTION_PRIV, _MMU_FAULT_BUFFER_GET, _OVERFLOW, _NO, getValue);
389         getValue = FLD_SET_DRF(_VIRTUAL_FUNCTION_PRIV, _MMU_FAULT_BUFFER_GET, _GETPTR_CORRUPTED, _NO, getValue);
390     }
391 
392     GPU_VREG_WR32_EX(pGpu, NV_VIRTUAL_FUNCTION_PRIV_MMU_FAULT_BUFFER_GET(index), getValue, pThreadState);
393 
394     return NV_OK;
395 }
396 
397 NV_STATUS
kgmmuReadFaultBufferPutPtr_TU102(OBJGPU * pGpu,KernelGmmu * pKernelGmmu,NvU32 index,NvU32 * pPutOffset,THREAD_STATE_NODE * pThreadState)398 kgmmuReadFaultBufferPutPtr_TU102
399 (
400     OBJGPU               *pGpu,
401     KernelGmmu           *pKernelGmmu,
402     NvU32                 index,
403     NvU32                *pPutOffset,
404     THREAD_STATE_NODE    *pThreadState
405 )
406 {
407     NvU32 val;
408     NV_ASSERT_OR_RETURN((index < NUM_FAULT_BUFFERS), NV_ERR_INVALID_ARGUMENT);
409 
410     val = GPU_VREG_RD32_EX(pGpu, NV_VIRTUAL_FUNCTION_PRIV_MMU_FAULT_BUFFER_PUT(index), pThreadState);
411     *pPutOffset = DRF_VAL(_VIRTUAL_FUNCTION_PRIV, _MMU_FAULT_BUFFER_PUT, _PTR, val);
412 
413     return NV_OK;
414 }
415 
416 /*!
417  * @brief Test if an MMU non-replayable fault is pending
418  *
419  * @param[in] pGpu
420  * @param[in] pKernelGmmu
421  *
422  * @returns NV_TRUE if an MMU non-replayable fault is pending, else NV_FALSE
423  */
424 NvBool
kgmmuIsNonReplayableFaultPending_TU102(OBJGPU * pGpu,KernelGmmu * pKernelGmmu,THREAD_STATE_NODE * pThreadState)425 kgmmuIsNonReplayableFaultPending_TU102
426 (
427     OBJGPU     *pGpu,
428     KernelGmmu *pKernelGmmu,
429     THREAD_STATE_NODE *pThreadState
430 )
431 {
432     NvU32 reg = NV_CTRL_INTR_GPU_VECTOR_TO_LEAF_REG(NV_PFB_PRI_MMU_INT_VECTOR_FAULT_NOTIFY_NON_REPLAYABLE);
433     NvU32 bit = NV_CTRL_INTR_GPU_VECTOR_TO_LEAF_BIT(NV_PFB_PRI_MMU_INT_VECTOR_FAULT_NOTIFY_NON_REPLAYABLE);
434     NvU32 pending = GPU_VREG_RD32_EX(pGpu, NV_VIRTUAL_FUNCTION_PRIV_CPU_INTR_LEAF(reg), pThreadState);
435     return pending & NVBIT(bit);
436 }
437 
438 /*!
439  * @brief Clear non replayable fault interrupt.
440  *
441  * @param[in] pGpu              OBJGPU pointer
442  * @param[in] pKernelGmmu       KernelGmmu pointer
443  * @param[in] pThreadState      THREAD_STATE_NODE pointer
444  */
445 void
kgmmuClearNonReplayableFaultIntr_TU102(OBJGPU * pGpu,KernelGmmu * pKernelGmmu,THREAD_STATE_NODE * pThreadState)446 kgmmuClearNonReplayableFaultIntr_TU102
447 (
448     OBJGPU            *pGpu,
449     KernelGmmu        *pKernelGmmu,
450     THREAD_STATE_NODE *pThreadState
451 )
452 {
453     Intr *pIntr = GPU_GET_INTR(pGpu);
454     intrClearLeafVector_HAL(pGpu, pIntr, NV_PFB_PRI_MMU_INT_VECTOR_FAULT_NOTIFY_NON_REPLAYABLE, pThreadState);
455 }
456 
457 /*!
458  * @brief Clear replayable fault interrupt.
459  *
460  * @param[in] pGpu              OBJGPU pointer
461  * @param[in] pKernelGmmu       KernelGmmu pointer
462  * @param[in] pThreadState      THREAD_STATE_NODE pointer
463  */
464 void
kgmmuClearReplayableFaultIntr_TU102(OBJGPU * pGpu,KernelGmmu * pKernelGmmu,THREAD_STATE_NODE * pThreadState)465 kgmmuClearReplayableFaultIntr_TU102
466 (
467     OBJGPU            *pGpu,
468     KernelGmmu        *pKernelGmmu,
469     THREAD_STATE_NODE *pThreadState
470 )
471 {
472     Intr *pIntr = GPU_GET_INTR(pGpu);
473     intrClearLeafVector_HAL(pGpu, pIntr, NV_PFB_PRI_MMU_INT_VECTOR_FAULT_NOTIFY_REPLAYABLE, pThreadState);
474 }
475 
476 /**
477  * @brief Print information about a MMU fault
478  *
479  * @param[in]  pGpu                  OBJGPU pointer
480  * @param[in]  pKernelGmmu           KernelGmmu pointer
481  * @param[in]  mmuFaultEngineId      Engine ID of the faulted engine
482  * @param[in]  pMmuExceptionData     FIFO exception packet used
483  *                                   for printing fault info
484  * @returns
485  */
486 void
kgmmuPrintFaultInfo_TU102(OBJGPU * pGpu,KernelGmmu * pKernelGmmu,NvU32 mmuFaultEngineId,FIFO_MMU_EXCEPTION_DATA * pMmuExceptionData)487 kgmmuPrintFaultInfo_TU102
488 (
489     OBJGPU                  *pGpu,
490     KernelGmmu              *pKernelGmmu,
491     NvU32                    mmuFaultEngineId,
492     FIFO_MMU_EXCEPTION_DATA *pMmuExceptionData
493 )
494 {
495     if (kmemsysCbcIsSafe_HAL(pGpu, GPU_GET_KERNEL_MEMORY_SYSTEM(pGpu)) == NV_FALSE)
496     {
497         NV_PRINTF(LEVEL_ERROR,
498                   "MMU Fault: CBC Backingstore unsafe, this can be reported as "
499                   "UNSUPPORTED_KIND error\n");
500     }
501 
502     void kgmmuPrintFaultInfo_GV100(OBJGPU *pGpu, KernelGmmu *pKernelGmmu, NvU32, FIFO_MMU_EXCEPTION_DATA*);
503     kgmmuPrintFaultInfo_GV100(pGpu, pKernelGmmu, mmuFaultEngineId, pMmuExceptionData);
504 }
505 
506 /*!
507  * @brief Check if the given engineID is BAR1
508  *
509  * @param[in] pKernelGmmu  KernelGmmu object
510  * @param[in] engineID     Engine ID
511  *
512  * @return True if BAR1
513  */
514 NvBool
kgmmuIsFaultEngineBar1_TU102(KernelGmmu * pKernelGmmu,NvU32 engineID)515 kgmmuIsFaultEngineBar1_TU102
516 (
517     KernelGmmu *pKernelGmmu,
518     NvU32       engineID
519 )
520 {
521     return (engineID == NV_PFAULT_MMU_ENG_ID_BAR1);
522 }
523 
524 /*!
525  * @brief Check if the given engineID is BAR2
526  *
527  * @param[in] pKernelGmmu  KernelGmmu object
528  * @param[in] engineID     Engine ID
529  *
530  * @return True if BAR2
531  */
532 
533 NvBool
kgmmuIsFaultEngineBar2_TU102(KernelGmmu * pKernelGmmu,NvU32 engineID)534 kgmmuIsFaultEngineBar2_TU102
535 (
536     KernelGmmu *pKernelGmmu,
537     NvU32       engineID
538 )
539 {
540     return (engineID == NV_PFAULT_MMU_ENG_ID_BAR2);
541 }
542 
543 /*!
544  * @brief Returns the HW default size of MMU fault buffers (replayable
545  *        or non replayable buffers).
546  *
547  * @param[in] pGpu         OBJGPU  pointer
548  * @param[in] pKernelGmmu  KernelGmmu pointer
549  * @param[in] index        Fault buffer index
550  *
551  * @returns size of MMU fault buffers
552  */
553 NvU32
kgmmuSetAndGetDefaultFaultBufferSize_TU102(OBJGPU * pGpu,KernelGmmu * pKernelGmmu,FAULT_BUFFER_TYPE index,NvU32 gfid)554 kgmmuSetAndGetDefaultFaultBufferSize_TU102
555 (
556     OBJGPU           *pGpu,
557     KernelGmmu       *pKernelGmmu,
558     FAULT_BUFFER_TYPE index,
559     NvU32             gfid
560 )
561 {
562     NvU32 faultBufferSize;
563     {
564         {
565             NV_ASSERT(IS_GFID_PF(gfid));
566 
567             GPU_VREG_FLD_IDX_WR_DRF_DEF(pGpu, _VIRTUAL_FUNCTION_PRIV, _MMU_FAULT_BUFFER_SIZE, index, _SET_DEFAULT, _YES);
568             faultBufferSize = GPU_VREG_IDX_RD_DRF(pGpu, _VIRTUAL_FUNCTION_PRIV, _MMU_FAULT_BUFFER_SIZE, index, _VAL) * NVC369_BUF_SIZE;
569         }
570     }
571 
572     return faultBufferSize;
573 }
574 
575 void
kgmmuWriteMmuFaultBufferSize_TU102(OBJGPU * pGpu,KernelGmmu * pKernelGmmu,NvU32 index,NvU32 value,NvU32 gfid)576 kgmmuWriteMmuFaultBufferSize_TU102
577 (
578     OBJGPU     *pGpu,
579     KernelGmmu *pKernelGmmu,
580     NvU32       index,
581     NvU32       value,
582     NvU32       gfid
583 )
584 {
585     {
586         NV_ASSERT(IS_GFID_PF(gfid));
587 
588         GPU_VREG_WR32(pGpu, NV_VIRTUAL_FUNCTION_PRIV_MMU_FAULT_BUFFER_SIZE(index), value);
589     }
590 
591     // Align the HW/SW _GET_PTR if _FAULT_BUFFER_SIZE_ENABLE is _FALSE which will be 0
592     if (FLD_TEST_DRF(_PFB_PRI, _MMU_FAULT_BUFFER_SIZE, _ENABLE, _FALSE, value))
593     {
594         pKernelGmmu->mmuFaultBuffer[gfid].hwFaultBuffers[index].cachedGetIndex = 0;
595     }
596 }
597 
598 void
kgmmuWriteMmuFaultBufferHiLo_TU102(OBJGPU * pGpu,KernelGmmu * pKernelGmmu,NvU32 index,NvU32 loValue,NvU32 hiValue,NvU32 gfid)599 kgmmuWriteMmuFaultBufferHiLo_TU102
600 (
601     OBJGPU     *pGpu,
602     KernelGmmu *pKernelGmmu,
603     NvU32       index,
604     NvU32       loValue,
605     NvU32       hiValue,
606     NvU32       gfid
607 )
608 {
609     {
610         NV_ASSERT(IS_GFID_PF(gfid));
611 
612         GPU_VREG_WR32(pGpu, NV_VIRTUAL_FUNCTION_PRIV_MMU_FAULT_BUFFER_HI(index), hiValue);
613         GPU_VREG_WR32(pGpu, NV_VIRTUAL_FUNCTION_PRIV_MMU_FAULT_BUFFER_LO(index), loValue);
614     }
615 }
616 
617 void
kgmmuReadMmuFaultInstHiLo_TU102(OBJGPU * pGpu,KernelGmmu * pKernelGmmu,NvU32 * pHiVal,NvU32 * pLoVal)618 kgmmuReadMmuFaultInstHiLo_TU102
619 (
620     OBJGPU     *pGpu,
621     KernelGmmu *pKernelGmmu,
622     NvU32      *pHiVal,
623     NvU32      *pLoVal
624 )
625 {
626     NV_ASSERT(pHiVal != NULL);
627     NV_ASSERT(pLoVal != NULL);
628     *pLoVal = GPU_VREG_RD32(pGpu, NV_VIRTUAL_FUNCTION_PRIV_MMU_FAULT_INST_LO);
629     *pHiVal = GPU_VREG_RD32(pGpu, NV_VIRTUAL_FUNCTION_PRIV_MMU_FAULT_INST_HI);
630 }
631 
632 void
kgmmuReadMmuFaultAddrHiLo_TU102(OBJGPU * pGpu,KernelGmmu * pKernelGmmu,NvU32 * pHiVal,NvU32 * pLoVal)633 kgmmuReadMmuFaultAddrHiLo_TU102
634 (
635     OBJGPU     *pGpu,
636     KernelGmmu *pKernelGmmu,
637     NvU32      *pHiVal,
638     NvU32      *pLoVal
639 )
640 {
641     NV_ASSERT(pHiVal != NULL);
642     NV_ASSERT(pLoVal != NULL);
643     *pLoVal = GPU_VREG_RD32(pGpu, NV_VIRTUAL_FUNCTION_PRIV_MMU_FAULT_ADDR_LO);
644     *pHiVal = GPU_VREG_RD32(pGpu, NV_VIRTUAL_FUNCTION_PRIV_MMU_FAULT_ADDR_HI);
645 }
646 
647 NvU32
kgmmuReadMmuFaultInfo_TU102(OBJGPU * pGpu,KernelGmmu * pKernelGmmu)648 kgmmuReadMmuFaultInfo_TU102
649 (
650     OBJGPU     *pGpu,
651     KernelGmmu *pKernelGmmu
652 )
653 {
654     return GPU_VREG_RD32(pGpu, NV_VIRTUAL_FUNCTION_PRIV_MMU_FAULT_INFO);
655 }
656 
657 NvU32
kgmmuGetEccCounts_TU102(OBJGPU * pGpu,KernelGmmu * pKernelGmmu)658 kgmmuGetEccCounts_TU102
659 (
660     OBJGPU     *pGpu,
661     KernelGmmu *pKernelGmmu
662 )
663 {
664     NvU32 mmuCount = 0;
665     NvU32 regVal;
666 
667     // L2TLB
668     regVal = GPU_REG_RD32(pGpu, NV_PFB_PRI_MMU_L2TLB_ECC_UNCORRECTED_ERR_COUNT);
669     mmuCount += DRF_VAL(_PFB_PRI_MMU, _L2TLB_ECC, _UNCORRECTED_ERR_COUNT_UNIQUE, regVal);
670 
671     // HUBTLB
672     regVal = GPU_REG_RD32(pGpu, NV_PFB_PRI_MMU_HUBTLB_ECC_UNCORRECTED_ERR_COUNT);
673     mmuCount += DRF_VAL(_PFB_PRI_MMU, _HUBTLB_ECC, _UNCORRECTED_ERR_COUNT_UNIQUE, regVal);
674 
675     // FILLUNIT
676     regVal = GPU_REG_RD32(pGpu, NV_PFB_PRI_MMU_FILLUNIT_ECC_UNCORRECTED_ERR_COUNT);
677     mmuCount += DRF_VAL(_PFB_PRI_MMU, _FILLUNIT_ECC, _UNCORRECTED_ERR_COUNT_UNIQUE, regVal);
678 
679     return mmuCount;
680 }
681