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