1 /*
2  * SPDX-FileCopyrightText: Copyright (c) 1993-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 #include "kernel/gpu/gpu.h"
25 #include "gpu_mgr/gpu_mgr.h"
26 #include "kernel/diagnostics/journal.h"
27 
28 #include "core/thread_state.h"
29 #include "platform/sli/sli.h"
30 #include "nv_ref.h"
31 
32 // Following enums are duplicated in 'apps/nvbucket/oca/ocarm.h'.
33 typedef enum {
34     BAD_READ_GPU_OFF_BUS = 1,
35     BAD_READ_LOW_POWER,
36     BAD_READ_PCI_DEVICE_DISABLED,
37     BAD_READ_GPU_RESET,
38     BAD_READ_DWORD_SHIFT,
39     BAD_READ_UNKNOWN,
40 } RMCD_BAD_READ_REASON;
41 
42 static void   _gpuCleanRegisterFilterList(DEVICE_REGFILTER_INFO *);
43 static NvU32  _gpuHandleReadRegisterFilter(OBJGPU *, DEVICE_INDEX devIndex, NvU32 devInstance, NvU32 addr, NvU32 accessSize, NvU32 *pFlags, THREAD_STATE_NODE *pThreadState);
44 static void   _gpuHandleWriteRegisterFilter(OBJGPU *, DEVICE_INDEX devIndex, NvU32 devInstance, NvU32 addr, NvU32 val, NvU32 accessSize, NvU32 *pFlags, THREAD_STATE_NODE *pThreadState);
45 
46 static void   ioaprtWriteRegUnicast(OBJGPU *, IoAperture *pAperture, NvU32 addr, NvV32 val, NvU32 size);
47 static NvU32  ioaprtReadReg(IoAperture *pAperture, NvU32 addr, NvU32 size);
48 
49 static REGISTER_FILTER * _findGpuRegisterFilter(DEVICE_INDEX devIndex, NvU32 devInstance, NvU32 addr, REGISTER_FILTER *);
50 static NV_STATUS _gpuInitIOAperture(OBJGPU *pGpu, NvU32 deviceIndex, DEVICE_MAPPING *pMapping);
51 
52 NV_STATUS
regAccessConstruct(RegisterAccess * pRegisterAccess,OBJGPU * pGpu)53 regAccessConstruct
54 (
55     RegisterAccess *pRegisterAccess,
56     OBJGPU *pGpu
57 )
58 {
59     NV_STATUS    rmStatus = NV_OK;
60     DEVICE_INDEX deviceIndex, minDeviceIndex, maxDeviceIndex;
61 
62     pRegisterAccess->pGpu = pGpu;
63 
64     if (pGpu->getProperty(pGpu, PDB_PROP_GPU_TEGRA_SOC_NVDISPLAY))
65     {
66         // DEVICE_INDEX_GPU aperture is of GPU, as Tegra SOC NvDisplay constructs
67         // display device IO aperture as part of objdisp construction so its safe to
68         // skip this function.
69         return NV_OK;
70     }
71 
72     // Check that GPU is the first device
73     ct_assert(DEVICE_INDEX_GPU == 0);
74 
75     minDeviceIndex = DEVICE_INDEX_GPU;
76     maxDeviceIndex = pGpu->bIsSOC ? (DEVICE_INDEX_MAX - 1) : (DEVICE_INDEX_GPU);
77 
78     for (deviceIndex = minDeviceIndex; deviceIndex <= maxDeviceIndex; deviceIndex++)
79     {
80         // Initialize IO Device and Aperture
81         DEVICE_MAPPING *pMapping = gpuGetDeviceMapping(pGpu, deviceIndex, 0);
82         if (pMapping != NULL)
83         {
84             rmStatus = _gpuInitIOAperture(pGpu, deviceIndex, pMapping);
85             if (rmStatus != NV_OK)
86             {
87                 NV_PRINTF(LEVEL_ERROR,
88                           "Failed to initialize pGpu IO device/aperture for deviceIndex=%d.\n", deviceIndex);
89                 return rmStatus;
90             }
91         }
92     }
93 
94     return rmStatus;
95 }
96 
97 void
regAccessDestruct(RegisterAccess * pRegisterAccess)98 regAccessDestruct
99 (
100     RegisterAccess *pRegisterAccess
101 )
102 {
103     OBJGPU         *pGpu = pRegisterAccess->pGpu;
104     DEVICE_INDEX    deviceIndex;
105     NvU32           mappingNum;
106     IoAperture     *pIOAperture;
107     REGISTER_FILTER *pNode;
108 
109     // Ignore attempt to destruct a not-fully-constructed RegisterAccess
110     if (pGpu == NULL)
111     {
112         return;
113     }
114 
115     for (deviceIndex = 0; deviceIndex < DEVICE_INDEX_MAX; deviceIndex++)
116     {
117         pIOAperture = pGpu->pIOApertures[deviceIndex];
118         if (pIOAperture != NULL)
119         {
120             objDelete(pIOAperture);
121         }
122     }
123 
124     for (mappingNum = 0; mappingNum < pGpu->gpuDeviceMapCount; mappingNum++)
125     {
126         // Device-specific register filter list
127         NV_ASSERT(!pGpu->deviceMappings[mappingNum].devRegFilterInfo.pRegFilterList);
128         if (NULL != pGpu->deviceMappings[mappingNum].devRegFilterInfo.pRegFilterLock)
129         {
130             portSyncSpinlockDestroy(pGpu->deviceMappings[mappingNum].devRegFilterInfo.pRegFilterLock);
131             pGpu->deviceMappings[mappingNum].devRegFilterInfo.pRegFilterLock = NULL;
132         }
133 
134         while (pGpu->deviceMappings[mappingNum].devRegFilterInfo.pRegFilterRecycleList)
135         {
136             pNode = pGpu->deviceMappings[mappingNum].devRegFilterInfo.pRegFilterRecycleList;
137 
138             pGpu->deviceMappings[mappingNum].devRegFilterInfo.pRegFilterRecycleList = pNode->pNext;
139             portMemFree(pNode);
140         }
141     }
142 }
143 
144 //
145 // The following register I/O functions are organized into two groups;
146 // a multi-chip unaware group and a multi-chip aware group.
147 // The multi-chip aware group of register I/O functions is also split
148 // into two groups; one that really does multi-chip logic and another
149 // that has the same interface but doesn't do any of the multi-chip
150 // logic.
151 //
152 // In the interests of performance, the determination as to whether
153 // multi-chip logic is necessary is done at two levels; the upper-level
154 // functions use 'MC' register I/O macros where multi-chip considerations
155 // are required, and when the 'MC' register I/O macros are used they
156 // call through GPU object pointers that are polymorphic - they contain
157 // pointers to one of the two groups of multi-chip aware functions
158 // depending on whether the multi-chip condition actually exists.
159 // This avoids a run-time SLI LOOP call.
160 //
161 static void
_regWriteUnicast(RegisterAccess * pRegisterAccess,DEVICE_INDEX deviceIndex,NvU32 instance,NvU32 addr,NvU32 val,NvU32 size,THREAD_STATE_NODE * pThreadState)162 _regWriteUnicast
163 (
164     RegisterAccess    *pRegisterAccess,
165     DEVICE_INDEX       deviceIndex,
166     NvU32              instance,
167     NvU32              addr,
168     NvU32              val,
169     NvU32              size,
170     THREAD_STATE_NODE *pThreadState
171 )
172 {
173     OBJGPU   *pGpu    = pRegisterAccess->pGpu;
174     NvU32     flags   = 0;
175     NV_STATUS status;
176     DEVICE_MAPPING *pMapping;
177 
178     pRegisterAccess->regWriteCount++;
179 
180     pMapping = gpuGetDeviceMapping(pGpu, deviceIndex, instance);
181     if (pMapping == NULL)
182     {
183         NV_PRINTF(LEVEL_ERROR,
184                   "Could not find mapping for reg %x, deviceIndex=0x%x instance=%d\n",
185                   addr, deviceIndex, instance);
186         NV_ASSERT(0);
187         return;
188     }
189 
190     status = gpuSanityCheckRegisterAccess(pGpu, addr, NULL);
191     if (status != NV_OK)
192     {
193         return;
194     }
195 
196     _gpuHandleWriteRegisterFilter(pGpu, deviceIndex, instance, addr, val, size, &flags, pThreadState);
197 
198     if (!(flags & REGISTER_FILTER_FLAGS_WRITE))
199     {
200         switch (size)
201         {
202             case 8:
203                 osDevWriteReg008(pGpu, pMapping, addr, 0xFFU & (val));
204                 break;
205             case 16:
206                 osDevWriteReg016(pGpu, pMapping, addr, 0xFFFFU & (val));
207                 break;
208             case 32:
209                 osDevWriteReg032(pGpu, pMapping, addr, val);
210                 break;
211         }
212     }
213 }
214 
215 /*!
216  * @brief: Initialize an IoAperture instance in-place.
217  *
218  * @param[out] pAperture        pointer to the IoAperture.
219  * @param[in]  pParentAperture  pointer to the parent of the new IoAperture.
220  * @param[in]  offset           offset from the parent APERTURE's baseAddress.
221  * @param[in]  length           length of the APERTURE.
222  *
223  * @return NV_OK upon success
224  *         NV_ERR* otherwise.
225  */
226 NV_STATUS
ioaprtInit(IoAperture * pAperture,IoAperture * pParentAperture,NvU32 offset,NvU32 length)227 ioaprtInit
228 (
229     IoAperture     *pAperture,
230     IoAperture     *pParentAperture,
231     NvU32           offset,
232     NvU32           length
233 )
234 {
235     return objCreateWithFlags(&pAperture, NVOC_NULL_OBJECT, IoAperture, NVOC_OBJ_CREATE_FLAGS_IN_PLACE_CONSTRUCT, pParentAperture, NULL, 0, 0, NULL, 0, offset, length);
236 }
237 
238 /*!
239  * Initialize an IoAperture instance.
240  *
241  * @param[in,out] pAperture        pointer to IoAperture instance to be initialized.
242  * @param[in]     pParentAperture  pointer to parent of the new IoAperture.
243  * @param[in]     deviceIndex      device index
244  * @param[in]     deviceInstance   device instance
245  * @param[in]     pMapping         device register mapping
246  * @param[in]     mappingStartAddr register address corresponding to the start of the mapping
247  * @param[in]     offset           offset from the parent APERTURE's baseAddress.
248  * @param[in]     length           length of the APERTURE.
249  *
250  * @return NV_OK when inputs are valid.
251  */
252 NV_STATUS
ioaprtConstruct_IMPL(IoAperture * pAperture,IoAperture * pParentAperture,OBJGPU * pGpu,NvU32 deviceIndex,NvU32 deviceInstance,DEVICE_MAPPING * pMapping,NvU32 mappingStartAddr,NvU32 offset,NvU32 length)253 ioaprtConstruct_IMPL
254 (
255     IoAperture      *pAperture,
256     IoAperture      *pParentAperture,
257     OBJGPU          *pGpu,
258     NvU32            deviceIndex,
259     NvU32            deviceInstance,
260     DEVICE_MAPPING  *pMapping,
261     NvU32            mappingStartAddr,
262     NvU32            offset,
263     NvU32            length
264 )
265 {
266     if (pParentAperture != NULL)
267     {
268         NV_ASSERT_OR_RETURN(pMapping == NULL, NV_ERR_INVALID_ARGUMENT);
269         NV_ASSERT_OR_RETURN(pGpu == NULL || pGpu == pParentAperture->pGpu, NV_ERR_INVALID_ARGUMENT);
270 
271         pAperture->pGpu = pParentAperture->pGpu;
272         pAperture->deviceIndex = pParentAperture->deviceIndex;
273         pAperture->deviceInstance = pParentAperture->deviceInstance;
274         pAperture->pMapping    = pParentAperture->pMapping;
275         pAperture->baseAddress = pParentAperture->baseAddress;
276         pAperture->mappingStartAddr = pParentAperture->mappingStartAddr;
277 
278         // Check if the child Aperture strides beyond the parent's boundary.
279         if ((length + offset) > pParentAperture->length)
280         {
281             NV_PRINTF(LEVEL_WARNING,
282                 "Child aperture crosses parent's boundary, length %u offset %u, Parent's length %u\n",
283                 length, offset, pParentAperture->length);
284         }
285 
286     }
287     else
288     {
289         NV_ASSERT_OR_RETURN(pMapping != NULL, NV_ERR_INVALID_ARGUMENT);
290         NV_ASSERT_OR_RETURN(pGpu != NULL, NV_ERR_INVALID_ARGUMENT);
291 
292         pAperture->pGpu = pGpu;
293         pAperture->deviceIndex = deviceIndex;
294         pAperture->deviceInstance = deviceInstance;
295         pAperture->pMapping = pMapping;
296         pAperture->baseAddress = 0;
297         pAperture->mappingStartAddr = mappingStartAddr;
298     }
299 
300     pAperture->baseAddress += offset;
301     pAperture->length       = length;
302 
303     return NV_OK;
304 }
305 
306 static void
ioaprtWriteRegUnicast(OBJGPU * pGpu,IoAperture * pAperture,NvU32 addr,NvV32 val,NvU32 size)307 ioaprtWriteRegUnicast
308 (
309     OBJGPU         *pGpu,
310     IoAperture     *pAperture,
311     NvU32           addr,
312     NvV32           val,
313     NvU32           size
314 )
315 {
316     NvU32              deviceIndex = pAperture->deviceIndex;
317     NvU32              instance    = pAperture->deviceInstance;
318     NvU32              regAddr     = pAperture->baseAddress + addr;
319     NvU32              mappingRegAddr = regAddr - pAperture->mappingStartAddr;
320     DEVICE_MAPPING    *pMapping    = pAperture->pMapping;
321     NvU32              flags       = 0;
322     NV_STATUS          status;
323     THREAD_STATE_NODE *pThreadState;
324 
325     if (!pGpu->getProperty(pGpu, PDB_PROP_GPU_TEGRA_SOC_NVDISPLAY))
326     {
327         status = gpuSanityCheckRegisterAccess(pGpu, regAddr, NULL);
328         if (status != NV_OK)
329         {
330             return;
331         }
332 
333         threadStateGetCurrentUnchecked(&pThreadState, pGpu);
334 
335         _gpuHandleWriteRegisterFilter(pGpu, deviceIndex, instance, regAddr,
336                                       val, size, &flags, pThreadState);
337     }
338 
339     if (!(flags & REGISTER_FILTER_FLAGS_WRITE))
340     {
341         switch (size)
342         {
343             case 8:
344                 osDevWriteReg008(pGpu, pMapping, mappingRegAddr, 0xFFU & (val));
345                 break;
346             case 16:
347                 osDevWriteReg016(pGpu, pMapping, mappingRegAddr, 0xFFFFU & (val));
348                 break;
349             case 32:
350                 osDevWriteReg032(pGpu, pMapping, mappingRegAddr, val);
351                 break;
352         }
353     }
354 }
355 
356 void
ioaprtWriteReg08_IMPL(IoAperture * pAperture,NvU32 addr,NvV8 val)357 ioaprtWriteReg08_IMPL
358 (
359     IoAperture     *pAperture,
360     NvU32           addr,
361     NvV8            val
362 )
363 {
364     NV_ASSERT(!gpumgrGetBcEnabledStatus(pAperture->pGpu));
365 
366     ioaprtWriteRegUnicast(pAperture->pGpu, pAperture, addr, val, 8 /* size */);
367 }
368 
369 void
ioaprtWriteReg16_IMPL(IoAperture * pAperture,NvU32 addr,NvV16 val)370 ioaprtWriteReg16_IMPL
371 (
372     IoAperture        *pAperture,
373     NvU32              addr,
374     NvV16              val
375 )
376 {
377     NV_ASSERT(!gpumgrGetBcEnabledStatus(pAperture->pGpu));
378 
379     ioaprtWriteRegUnicast(pAperture->pGpu, pAperture, addr, val, 16 /* size */);
380 }
381 
382 void
ioaprtWriteReg32_IMPL(IoAperture * pAperture,NvU32 addr,NvV32 val)383 ioaprtWriteReg32_IMPL
384 (
385     IoAperture        *pAperture,
386     NvU32              addr,
387     NvV32              val
388 )
389 {
390     NV_ASSERT(!gpumgrGetBcEnabledStatus(pAperture->pGpu));
391 
392     ioaprtWriteRegUnicast(pAperture->pGpu, pAperture, addr, val, 32 /* size */);
393 }
394 
395 void
ioaprtWriteReg32Uc_IMPL(IoAperture * pAperture,NvU32 addr,NvV32 val)396 ioaprtWriteReg32Uc_IMPL
397 (
398     IoAperture        *pAperture,
399     NvU32              addr,
400     NvV32              val
401 )
402 {
403     ioaprtWriteRegUnicast(pAperture->pGpu, pAperture, addr, val, 32 /* size */);
404 }
405 
406 void
regWrite008(RegisterAccess * pRegisterAccess,DEVICE_INDEX deviceIndex,NvU32 instance,NvU32 addr,NvV8 val)407 regWrite008
408 (
409     RegisterAccess *pRegisterAccess,
410     DEVICE_INDEX    deviceIndex,
411     NvU32           instance,
412     NvU32           addr,
413     NvV8            val
414 )
415 {
416     OBJGPU *pGpu = pRegisterAccess->pGpu;
417 
418     SLI_LOOP_START(SLI_LOOP_FLAGS_BC_ONLY);
419         _regWriteUnicast(GPU_GET_REGISTER_ACCESS(pGpu), deviceIndex, instance, addr, val, 8, NULL);
420     SLI_LOOP_END;
421 }
422 void
regWrite016(RegisterAccess * pRegisterAccess,DEVICE_INDEX deviceIndex,NvU32 instance,NvU32 addr,NvV16 val)423 regWrite016
424 (
425     RegisterAccess *pRegisterAccess,
426     DEVICE_INDEX    deviceIndex,
427     NvU32           instance,
428     NvU32           addr,
429     NvV16           val
430 )
431 {
432     OBJGPU *pGpu = pRegisterAccess->pGpu;
433 
434     SLI_LOOP_START(SLI_LOOP_FLAGS_BC_ONLY);
435         _regWriteUnicast(GPU_GET_REGISTER_ACCESS(pGpu), deviceIndex, instance, addr, val, 16, NULL);
436     SLI_LOOP_END;
437 }
438 
439 void
regWrite032(RegisterAccess * pRegisterAccess,DEVICE_INDEX deviceIndex,NvU32 instance,NvU32 addr,NvV32 val,THREAD_STATE_NODE * pThreadState)440 regWrite032
441 (
442     RegisterAccess    *pRegisterAccess,
443     DEVICE_INDEX       deviceIndex,
444     NvU32              instance,
445     NvU32              addr,
446     NvV32              val,
447     THREAD_STATE_NODE *pThreadState
448 )
449 {
450     OBJGPU *pGpu = pRegisterAccess->pGpu;
451 
452     SLI_LOOP_START(SLI_LOOP_FLAGS_BC_ONLY);
453         regWrite032Unicast(GPU_GET_REGISTER_ACCESS(pGpu), deviceIndex, instance, addr, val, pThreadState);
454     SLI_LOOP_END
455 }
456 
457 void
regWrite032Unicast(RegisterAccess * pRegisterAccess,DEVICE_INDEX deviceIndex,NvU32 instance,NvU32 addr,NvV32 val,THREAD_STATE_NODE * pThreadState)458 regWrite032Unicast
459 (
460     RegisterAccess    *pRegisterAccess,
461     DEVICE_INDEX       deviceIndex,
462     NvU32              instance,
463     NvU32              addr,
464     NvV32              val,
465     THREAD_STATE_NODE *pThreadState
466 )
467 {
468 
469     _regWriteUnicast(pRegisterAccess, deviceIndex, instance, addr, val, 32, pThreadState);
470 }
471 
472 static NvU32
ioaprtReadReg(IoAperture * pAperture,NvU32 addr,NvU32 size)473 ioaprtReadReg
474 (
475     IoAperture     *pAperture,
476     NvU32           addr,
477     NvU32           size
478 )
479 {
480     NvU32              flags       = 0;
481     NvU32              returnValue = 0;
482     OBJGPU            *pGpu        = pAperture->pGpu;
483     NV_STATUS          status      = NV_OK;
484     NvU32              regAddr     = pAperture->baseAddress + addr;
485     NvU32              mappingRegAddr = regAddr - pAperture->mappingStartAddr;
486     NvU32              deviceIndex = pAperture->deviceIndex;
487     NvU32              instance    = pAperture->deviceInstance;
488     DEVICE_MAPPING    *pMapping    = pAperture->pMapping;
489     THREAD_STATE_NODE *pThreadState;
490 
491     pGpu->registerAccess.regReadCount++;
492 
493     if (!pGpu->getProperty(pGpu, PDB_PROP_GPU_TEGRA_SOC_NVDISPLAY))
494     {
495         status = gpuSanityCheckRegisterAccess(pGpu, regAddr, NULL);
496         if (status != NV_OK)
497         {
498             return (~0);
499         }
500 
501         threadStateGetCurrentUnchecked(&pThreadState, pGpu);
502 
503         returnValue = _gpuHandleReadRegisterFilter(pGpu, deviceIndex, instance,
504                                                    regAddr, size, &flags, pThreadState);
505     }
506 
507     if (!(flags & REGISTER_FILTER_FLAGS_READ))
508     {
509         switch (size)
510         {
511             case 8:
512                 returnValue = osDevReadReg008(pGpu, pMapping, mappingRegAddr);
513                 break;
514             case 16:
515                 returnValue = osDevReadReg016(pGpu, pMapping, mappingRegAddr);
516                 break;
517             case 32:
518                 returnValue = osDevReadReg032(pGpu, pMapping, mappingRegAddr);
519                 break;
520         }
521     }
522 
523     if (!pGpu->getProperty(pGpu, PDB_PROP_GPU_TEGRA_SOC_NVDISPLAY))
524     {
525         // Make sure the value read is sane before we party on it.
526         gpuSanityCheckRegRead(pGpu, regAddr, size, &returnValue);
527     }
528 
529     return returnValue;
530 }
531 
532 NvU8
ioaprtReadReg08_IMPL(IoAperture * pAperture,NvU32 addr)533 ioaprtReadReg08_IMPL
534 (
535     IoAperture     *pAperture,
536     NvU32           addr
537 )
538 {
539     return (NvU8) ioaprtReadReg(pAperture, addr, 8 /* size */);
540 }
541 
542 NvU16
ioaprtReadReg16_IMPL(IoAperture * pAperture,NvU32 addr)543 ioaprtReadReg16_IMPL
544 (
545     IoAperture     *pAperture,
546     NvU32           addr
547 )
548 {
549     return (NvU16) ioaprtReadReg(pAperture, addr, 16 /* size */);
550 }
551 
552 NvU32
ioaprtReadReg32_IMPL(IoAperture * pAperture,NvU32 addr)553 ioaprtReadReg32_IMPL
554 (
555     IoAperture        *pAperture,
556     NvU32              addr
557 
558 )
559 {
560     return ioaprtReadReg(pAperture, addr, 32 /* size */);
561 }
562 
563 /*!
564  * Checks if the register address is valid for a particular aperture
565  *
566  * @param[in]       pAperture       IoAperture pointer
567  * @param[in]       addr            register address
568  *
569  * @returns         NV_TRUE         Register offset is valid
570  */
571 NvBool
ioaprtIsRegValid_IMPL(IoAperture * pAperture,NvU32 addr)572 ioaprtIsRegValid_IMPL
573 (
574     IoAperture     *pAperture,
575     NvU32           addr
576 )
577 {
578     NV_ASSERT_OR_RETURN(pAperture != NULL, NV_FALSE);
579 
580     return addr < pAperture->length;
581 }
582 
583 static NvU32
_regRead(RegisterAccess * pRegisterAccess,DEVICE_INDEX deviceIndex,NvU32 instance,NvU32 addr,NvU32 size,THREAD_STATE_NODE * pThreadState)584 _regRead
585 (
586     RegisterAccess    *pRegisterAccess,
587     DEVICE_INDEX       deviceIndex,
588     NvU32              instance,
589     NvU32              addr,
590     NvU32              size,
591     THREAD_STATE_NODE *pThreadState
592 )
593 {
594     NvU32     flags       = 0;
595     NvU32     returnValue = 0;
596     OBJGPU   *pGpu        = pRegisterAccess->pGpu;
597     DEVICE_MAPPING *pMapping;
598     NV_STATUS status      = NV_OK;
599 
600     pRegisterAccess->regReadCount++;
601 
602     pMapping = gpuGetDeviceMapping(pGpu, deviceIndex, instance);
603     if (pMapping == NULL)
604     {
605         NV_PRINTF(LEVEL_ERROR,
606                   "Could not find mapping for reg %x, deviceIndex=0x%x instance=%d\n",
607                   addr, deviceIndex, instance);
608         NV_ASSERT(0);
609         return 0xd0d0d0d0;
610     }
611 
612     if ((size == 32) &&
613         pGpu->getProperty(pGpu, PDB_PROP_GPU_IN_BUGCHECK_CALLBACK_ROUTINE))
614     {
615         return osDevReadReg032(pGpu, pMapping, addr);
616     }
617 
618     status = gpuSanityCheckRegisterAccess(pGpu, addr, &returnValue);
619     if (status != NV_OK)
620         return returnValue;
621 
622     returnValue = _gpuHandleReadRegisterFilter(pGpu, deviceIndex, instance,
623                                                addr, size, &flags, pThreadState);
624 
625     if (!(flags & REGISTER_FILTER_FLAGS_READ))
626     {
627         switch (size)
628         {
629             case 8:
630                 returnValue = osDevReadReg008(pGpu, pMapping, addr);
631                 break;
632             case 16:
633                 returnValue = osDevReadReg016(pGpu, pMapping, addr);
634                 break;
635             case 32:
636                 returnValue = osDevReadReg032(pGpu, pMapping, addr);
637                 break;
638         }
639     }
640 
641     // Make sure the value read is sane before we party on it.
642     gpuSanityCheckRegRead(pGpu, addr, size, &returnValue);
643 
644     return returnValue;
645 }
646 
647 NvU8
regRead008(RegisterAccess * pRegisterAccess,DEVICE_INDEX deviceIndex,NvU32 instance,NvU32 addr)648 regRead008
649 (
650     RegisterAccess *pRegisterAccess,
651     DEVICE_INDEX    deviceIndex,
652     NvU32           instance,
653     NvU32           addr
654 )
655 {
656     return _regRead(pRegisterAccess, deviceIndex, instance, addr, 8, NULL);
657 }
658 
659 NvU16
regRead016(RegisterAccess * pRegisterAccess,DEVICE_INDEX deviceIndex,NvU32 instance,NvU32 addr)660 regRead016
661 (
662     RegisterAccess *pRegisterAccess,
663     DEVICE_INDEX    deviceIndex,
664     NvU32           instance,
665     NvU32           addr
666 )
667 {
668     return _regRead(pRegisterAccess, deviceIndex, instance, addr, 16, NULL);
669 }
670 
671 /*!
672  * This function is used for converting do-while read register constructs in RM to
673  * equivalent PMU sequencer handling. The idea is to construct seq instruction
674  * which polls on a field in the given register.
675  *
676  * @param[in]       pRegisterAccess RegisterAccess object pointer
677  * @param[in]       deviceIndex     deviceIndex
678  * @param[in]       addr            register address
679  * @param[in]       mask            required mask for the field
680  * @param[in]       val             value to poll for
681  *
682  * @returns         NV_OK           if val is found
683  *                  NV_ERR_TIMEOUT  if val is not found within timeout limit
684  */
685 NV_STATUS
regRead032_AndPoll(RegisterAccess * pRegisterAccess,DEVICE_INDEX deviceIndex,NvU32 addr,NvU32 mask,NvU32 val)686 regRead032_AndPoll
687 (
688     RegisterAccess   *pRegisterAccess,
689     DEVICE_INDEX      deviceIndex,
690     NvU32             addr,
691     NvU32             mask,
692     NvU32             val
693 )
694 {
695     RMTIMEOUT  timeout;
696     OBJGPU    *pGpu = pRegisterAccess->pGpu;
697     NvU32      data = 0;
698     NV_STATUS  status = NV_OK;
699 
700     {
701         gpuSetTimeout(pGpu, GPU_TIMEOUT_DEFAULT, &timeout, 0);
702 
703         do
704         {
705             data = GPU_REG_RD32(pGpu, addr);
706 
707             if ((data & mask) == val)
708             {
709                 status = NV_OK;
710                 break;
711             }
712 
713             // Loosen this loop
714             osSpinLoop();
715 
716             status = gpuCheckTimeout(pGpu, &timeout);
717         } while (status != NV_ERR_TIMEOUT);
718     }
719 
720     return status;
721 }
722 
723 NvU32
regRead032(RegisterAccess * pRegisterAccess,DEVICE_INDEX deviceIndex,NvU32 instance,NvU32 addr,THREAD_STATE_NODE * pThreadState)724 regRead032
725 (
726     RegisterAccess    *pRegisterAccess,
727     DEVICE_INDEX       deviceIndex,
728     NvU32              instance,
729     NvU32              addr,
730     THREAD_STATE_NODE *pThreadState
731 )
732 {
733     if (pRegisterAccess == NULL)
734     {
735         return NV_ERR_INVALID_POINTER;
736     }
737 
738     return _regRead(pRegisterAccess, deviceIndex, instance, addr, 32, pThreadState);
739 }
740 
741 /*!
742  * @brief Allocates and initializes GPU_IO_DEVICE and IO Aperture.
743  *
744  * @param     pGpu
745  * @param[in] deviceIndex   DEVICE_INDEX enum value for identifying device type
746  * @param[in] gpuDeviceEnum Device ID NV_DEVID_*
747  * @param[in] gpuNvPAddr    Physical Base Address
748  * @param[in] gpuNvLength   Length of Aperture
749  *
750  * @return NV_OK if IO Aperture is successfully initialized, error otherwise.
751  */
752 static NV_STATUS
_gpuInitIOAperture(OBJGPU * pGpu,NvU32 deviceIndex,DEVICE_MAPPING * pMapping)753 _gpuInitIOAperture
754 (
755     OBJGPU         *pGpu,
756     NvU32           deviceIndex,
757     DEVICE_MAPPING *pMapping
758 )
759 {
760     NV_STATUS rmStatus;
761 
762     rmStatus = objCreate(&pGpu->pIOApertures[deviceIndex], NVOC_NULL_OBJECT, IoAperture,
763                          NULL, // no parent aperture
764                          pGpu,
765                          deviceIndex,
766                          0, // GPU register operations are always on instance 0
767                          pMapping, 0, // mapping, mappingStartAddr
768                          0, pMapping->gpuNvLength); // offset, length
769     if (rmStatus != NV_OK)
770     {
771         NV_PRINTF(LEVEL_ERROR,
772                   "Failed to initialize pGpu IO aperture for devIdx %d.\n",
773                   deviceIndex);
774 
775         return rmStatus;
776     }
777 
778     return NV_OK;
779 }
780 
781 
782 NV_STATUS
regAddRegisterFilter(RegisterAccess * pRegisterAccess,NvU32 flags,DEVICE_INDEX devIndex,NvU32 devInstance,NvU32 rangeStart,NvU32 rangeEnd,GpuWriteRegCallback pWriteCallback,GpuReadRegCallback pReadCallback,void * pParam,REGISTER_FILTER ** ppFilter)783 regAddRegisterFilter
784 (
785     RegisterAccess *pRegisterAccess,
786     NvU32 flags,
787     DEVICE_INDEX devIndex, NvU32 devInstance,
788     NvU32 rangeStart, NvU32 rangeEnd,
789     GpuWriteRegCallback pWriteCallback,
790     GpuReadRegCallback pReadCallback,
791     void *pParam,
792     REGISTER_FILTER **ppFilter
793 )
794 {
795     DEVICE_REGFILTER_INFO *pRegFilter;
796     REGISTER_FILTER     *pNode;
797     REGISTER_FILTER     *pTmpNode;
798     DEVICE_MAPPING      *pMapping;
799 
800     NV_ASSERT_OR_RETURN(devIndex < DEVICE_INDEX_MAX, NV_ERR_INVALID_ARGUMENT);
801     NV_ASSERT_OR_RETURN(pRegisterAccess != NULL, NV_ERR_INVALID_ARGUMENT);
802     NV_ASSERT_OR_RETURN(ppFilter != NULL, NV_ERR_INVALID_ARGUMENT);
803 
804     // Get the device filter
805     pMapping = gpuGetDeviceMapping(pRegisterAccess->pGpu, devIndex, devInstance);
806     NV_ASSERT_OR_RETURN(pMapping != NULL, NV_ERR_INVALID_ARGUMENT);
807 
808     pRegFilter = &pMapping->devRegFilterInfo;
809 
810     if (!pWriteCallback && !pReadCallback)
811     {
812         // At least one register callback needs to be passed.
813         NV_PRINTF(LEVEL_ERROR,
814                   "Need to specify at least one callback function.\n");
815 
816         return NV_ERR_NOT_SUPPORTED;
817     }
818 
819     NV_ASSERT(!(flags & REGISTER_FILTER_FLAGS_INVALID));
820 
821     if ((flags & REGISTER_FILTER_FLAGS_READ) && !pReadCallback)
822     {
823         // If REGISTER_FILTER_FLAGS_READ is specified, then a read
824         // callback must also be specified.
825         NV_PRINTF(LEVEL_ERROR,
826                   "REGISTER_FILTER_FLAGS_READ requires a read callback function.\n");
827 
828         return NV_ERR_INVALID_ARGUMENT;
829     }
830 
831     if ((flags & REGISTER_FILTER_FLAGS_WRITE) && !pWriteCallback)
832     {
833         // If REGISTER_FILTER_FLAGS_WRITE is specified, then a write
834         // callback must also be specified.
835         NV_PRINTF(LEVEL_ERROR,
836                   "REGISTER_FILTER_FLAGS_WRITE requires a write callback function.\n");
837 
838         return NV_ERR_INVALID_ARGUMENT;
839     }
840 
841     // If the regfilter hasn't been used yet, then allocate a lock
842     if (NULL == pRegFilter->pRegFilterLock)
843     {
844         // Allocate spinlock for reg filter access
845         pRegFilter->pRegFilterLock = portSyncSpinlockCreate(portMemAllocatorGetGlobalNonPaged());
846         NV_ASSERT_OR_RETURN(pRegFilter->pRegFilterLock != NULL, NV_ERR_INSUFFICIENT_RESOURCES);
847     }
848 
849     portSyncSpinlockAcquire(pRegFilter->pRegFilterLock);
850 
851     if (NULL != pRegFilter->pRegFilterRecycleList)
852     {
853         pNode = pRegFilter->pRegFilterRecycleList;
854         pRegFilter->pRegFilterRecycleList = pNode->pNext;
855     }
856     else
857     {
858         portSyncSpinlockRelease(pRegFilter->pRegFilterLock);
859         pNode = portMemAllocNonPaged(sizeof(REGISTER_FILTER));
860         if (NULL == pNode)
861         {
862             return NV_ERR_NO_MEMORY;
863         }
864         portSyncSpinlockAcquire(pRegFilter->pRegFilterLock);
865     }
866 
867     // Print a warning if there's another register filter already registered.
868     if (((pTmpNode = _findGpuRegisterFilter(devIndex, devInstance, rangeStart, pRegFilter->pRegFilterList)) != NULL) ||
869         ((pTmpNode = _findGpuRegisterFilter(devIndex, devInstance, rangeEnd,   pRegFilter->pRegFilterList)) != NULL))
870     {
871             NV_PRINTF(LEVEL_WARNING,
872                       "WARNING!! Previously registered reg filter found. Handle: %p, dev: "
873                       "%d(%d) Range : 0x%x - 0x%x, WR/RD Callback: %p/%p, flags : %x\n",
874                       pTmpNode, pTmpNode->devIndex, pTmpNode->devInstance,
875                       pTmpNode->rangeStart, pTmpNode->rangeEnd,
876                       pTmpNode->pWriteCallback, pTmpNode->pReadCallback,
877                       pTmpNode->flags);
878     }
879 
880     // Populate structure
881     pNode->flags          = flags;
882     pNode->devIndex       = devIndex;
883     pNode->devInstance    = devInstance;
884     pNode->rangeStart     = rangeStart;
885     pNode->rangeEnd       = rangeEnd;
886     pNode->pWriteCallback = pWriteCallback;
887     pNode->pReadCallback  = pReadCallback;
888     pNode->pParam         = pParam;
889 
890     // Link in
891     pNode->pNext = pRegFilter->pRegFilterList;
892     pRegFilter->pRegFilterList = pNode;
893 
894     // return pNode
895     *ppFilter = pNode;
896 
897     portSyncSpinlockRelease(pRegFilter->pRegFilterLock);
898     return NV_OK;
899 }
900 
901 void
regRemoveRegisterFilter(RegisterAccess * pRegisterAccess,REGISTER_FILTER * pFilter)902 regRemoveRegisterFilter
903 (
904     RegisterAccess *pRegisterAccess,
905     REGISTER_FILTER *pFilter
906 )
907 {
908     REGISTER_FILTER       *pNode;
909     REGISTER_FILTER       *pPrev = NULL;
910     REGISTER_FILTER       *pNext = NULL;
911     DEVICE_REGFILTER_INFO *pRegFilter;
912     DEVICE_MAPPING        *pMapping;
913 
914     // Get the device filter
915     pMapping = gpuGetDeviceMapping(pRegisterAccess->pGpu, pFilter->devIndex, pFilter->devInstance);
916     NV_ASSERT_OR_RETURN_VOID(pMapping != NULL);
917 
918     pRegFilter = &pMapping->devRegFilterInfo;
919 
920     portSyncSpinlockAcquire(pRegFilter->pRegFilterLock);
921     pNode = pRegFilter->pRegFilterList;
922     while (pNode)
923     {
924         //
925         // we could have used a doubly linked list to do a quick removal, but
926         // iterating the list to find the match serves as sanity test, so let's
927         // stick with a singly linked list.
928         //
929         if (pNode == pFilter)
930         {
931             if (pRegFilter->regFilterRefCnt > 0)
932             {
933                 // defer removal if another thread is working on the list
934                 pNode->flags |= REGISTER_FILTER_FLAGS_INVALID;
935                 pRegFilter->bRegFilterNeedRemove = NV_TRUE;
936                 portSyncSpinlockRelease(pRegFilter->pRegFilterLock);
937                 return;
938             }
939 
940             // Unlink
941             pNext = pNode->pNext;
942 
943             // place on recycle list
944             pNode->pNext = pRegFilter->pRegFilterRecycleList;
945             pRegFilter->pRegFilterRecycleList = pNode;
946 
947             if (pPrev)
948             {
949                 pPrev->pNext = pNext;
950             }
951             else
952             {
953                 pRegFilter->pRegFilterList = pNext;
954             }
955 
956             portSyncSpinlockRelease(pRegFilter->pRegFilterLock);
957             return;
958         }
959 
960         pPrev = pNode;
961         pNode = pNode->pNext;
962     }
963     NV_ASSERT_FAILED("Attempted to remove a nonexistent filter");
964     portSyncSpinlockRelease(pRegFilter->pRegFilterLock);
965 }
966 
967 // called with lock held
968 static void
_gpuCleanRegisterFilterList(DEVICE_REGFILTER_INFO * pRegFilter)969 _gpuCleanRegisterFilterList
970 (
971     DEVICE_REGFILTER_INFO *pRegFilter
972 )
973 {
974     REGISTER_FILTER *pNode = pRegFilter->pRegFilterList;
975     REGISTER_FILTER *pPrev = NULL;
976     REGISTER_FILTER *pNext = NULL;
977 
978     while (pNode)
979     {
980         if (pNode->flags & REGISTER_FILTER_FLAGS_INVALID)
981         {
982             // Unlink
983             pNext = pNode->pNext;
984 
985             // place on recycle list
986             pNode->pNext = pRegFilter->pRegFilterRecycleList;
987             pRegFilter->pRegFilterRecycleList = pNode;
988 
989             if (pPrev)
990             {
991                 pPrev->pNext = pNext;
992             }
993             else
994             {
995                 pRegFilter->pRegFilterList = pNext;
996             }
997 
998             pNode = pNext;
999             continue;
1000         }
1001 
1002         pPrev = pNode;
1003         pNode = pNode->pNext;
1004     }
1005 }
1006 
1007 static NvU32
_gpuHandleReadRegisterFilter(OBJGPU * pGpu,DEVICE_INDEX devIndex,NvU32 devInstance,NvU32 addr,NvU32 accessSize,NvU32 * pFlags,THREAD_STATE_NODE * pThreadState)1008 _gpuHandleReadRegisterFilter
1009 (
1010     OBJGPU            *pGpu,
1011     DEVICE_INDEX       devIndex,
1012     NvU32              devInstance,
1013     NvU32              addr,
1014     NvU32              accessSize,
1015     NvU32             *pFlags,
1016     THREAD_STATE_NODE *pThreadState
1017 )
1018 {
1019     REGISTER_FILTER       *pFilter;
1020     NvU32                  returnValue = 0;
1021     NvU32                  tempVal     = 0;
1022     DEVICE_REGFILTER_INFO *pRegFilter;
1023     DEVICE_MAPPING        *pMapping;
1024 
1025     // Get the device filter
1026     pMapping = gpuGetDeviceMapping(pGpu, devIndex, devInstance);
1027     NV_ASSERT_OR_RETURN(pMapping != NULL, returnValue);
1028 
1029     pRegFilter = &pMapping->devRegFilterInfo;
1030 
1031     // if there is no filter, do nothing. just bail out.
1032     if (pRegFilter->pRegFilterList == NULL)
1033     {
1034         return returnValue;
1035     }
1036 
1037     if (pThreadState != NULL)
1038     {
1039         // Filters should be only used with GPU lock is held.
1040         if (pThreadState->flags & THREAD_STATE_FLAGS_IS_ISR_LOCKLESS)
1041         {
1042             return returnValue;
1043         }
1044     }
1045 #ifdef DEBUG
1046     else
1047     {
1048         THREAD_STATE_NODE *pCurThread;
1049 
1050         if (NV_OK == threadStateGetCurrentUnchecked(&pCurThread, pGpu))
1051         {
1052             // Filters should be only used with GPU lock is held.
1053             // Assert because ISRs are expected to pass threadstate down the stack.
1054             // Don't bale out to keep release and debug path behavior identical.
1055             if (pCurThread->flags & THREAD_STATE_FLAGS_IS_ISR_LOCKLESS)
1056             {
1057                 NV_ASSERT(0);
1058             }
1059         }
1060     }
1061 #endif
1062 
1063     //
1064     // NOTE: we can't simply grab the lock and release it after
1065     //       the search since it is not safe to assume that
1066     //       callbacks can be called with spinlock held
1067     //
1068     portSyncSpinlockAcquire(pRegFilter->pRegFilterLock);
1069     pRegFilter->regFilterRefCnt++;
1070     portSyncSpinlockRelease(pRegFilter->pRegFilterLock);
1071 
1072     //
1073     // Note there is potential thread race condition where a filter may be
1074     // being added or removed in one thread (dispatch) while another thread
1075     // is searching the list.  This search should have a lock in place.
1076     //
1077     pFilter = pRegFilter->pRegFilterList;
1078     while ((pFilter) && (pFilter = _findGpuRegisterFilter(devIndex, devInstance, addr, pFilter)))
1079     {
1080         if (pFilter->pReadCallback)
1081         {
1082             tempVal = pFilter->pReadCallback(pGpu, pFilter->pParam, addr,
1083                                              accessSize, *pFlags);
1084             //
1085             // if there are multiple filters, we use the last filter found to
1086             // save returnValue
1087             //
1088             if (pFilter->flags & REGISTER_FILTER_FLAGS_READ)
1089             {
1090                 returnValue = tempVal;
1091             }
1092         }
1093         *pFlags |= pFilter->flags;
1094         pFilter = pFilter->pNext;
1095     }
1096 
1097     portSyncSpinlockAcquire(pRegFilter->pRegFilterLock);
1098     pRegFilter->regFilterRefCnt--;
1099     if (pRegFilter->regFilterRefCnt == 0 && pRegFilter->bRegFilterNeedRemove)
1100     {
1101         // no other thread can be touching the list. remove invalid entries
1102         _gpuCleanRegisterFilterList(pRegFilter);
1103         pRegFilter->bRegFilterNeedRemove = NV_FALSE;
1104     }
1105     portSyncSpinlockRelease(pRegFilter->pRegFilterLock);
1106     return returnValue;
1107 }
1108 
1109 static void
_gpuHandleWriteRegisterFilter(OBJGPU * pGpu,DEVICE_INDEX devIndex,NvU32 devInstance,NvU32 addr,NvU32 val,NvU32 accessSize,NvU32 * pFlags,THREAD_STATE_NODE * pThreadState)1110 _gpuHandleWriteRegisterFilter
1111 (
1112     OBJGPU            *pGpu,
1113     DEVICE_INDEX       devIndex,
1114     NvU32              devInstance,
1115     NvU32              addr,
1116     NvU32              val,
1117     NvU32              accessSize,
1118     NvU32             *pFlags,
1119     THREAD_STATE_NODE *pThreadState
1120 )
1121 {
1122     REGISTER_FILTER       *pFilter;
1123     DEVICE_REGFILTER_INFO *pRegFilter;
1124     DEVICE_MAPPING        *pMapping;
1125 
1126     // Get the device filter
1127     pMapping = gpuGetDeviceMapping(pGpu, devIndex, devInstance);
1128     NV_ASSERT_OR_RETURN_VOID(pMapping != NULL);
1129 
1130     pRegFilter = &pMapping->devRegFilterInfo;
1131 
1132     // if there is no filter, do nothing. just bail out.
1133     if (pRegFilter->pRegFilterList == NULL)
1134     {
1135         return;
1136     }
1137 
1138     if (pThreadState != NULL)
1139     {
1140         // Filters should be only used with GPU lock is held.
1141         if (pThreadState->flags & THREAD_STATE_FLAGS_IS_ISR_LOCKLESS)
1142         {
1143             return;
1144         }
1145     }
1146 #ifdef DEBUG
1147     else
1148     {
1149         THREAD_STATE_NODE *pCurThread;
1150 
1151         if (NV_OK == threadStateGetCurrentUnchecked(&pCurThread, pGpu))
1152         {
1153             // Filters should be only used with GPU lock is held.
1154             // Assert because ISRs are expected to pass threadstate down the stack.
1155             // Don't bale out to keep release and debug path behavior identical.
1156             if (pCurThread->flags & THREAD_STATE_FLAGS_IS_ISR_LOCKLESS)
1157             {
1158                 NV_ASSERT(0);
1159             }
1160         }
1161     }
1162 #endif
1163 
1164     //
1165     // NOTE: we can't simply grab the lock and release it after
1166     //       the search since it is not safe to assume that
1167     //       callbacks can be called with spinlock held
1168     //
1169     portSyncSpinlockAcquire(pRegFilter->pRegFilterLock);
1170     pRegFilter->regFilterRefCnt++;
1171     portSyncSpinlockRelease(pRegFilter->pRegFilterLock);
1172 
1173     //
1174     // Note there is potential thread race condition where a filter may be
1175     // being added or removed in one thread (dispatch) while another thread
1176     // is searching the list.  This search should have a lock in place.
1177     //
1178     pFilter = pRegFilter->pRegFilterList;
1179     while ((pFilter) && (pFilter = _findGpuRegisterFilter(devIndex, devInstance, addr, pFilter)))
1180     {
1181         if (pFilter->pWriteCallback)
1182         {
1183             pFilter->pWriteCallback(pGpu, pFilter->pParam, addr, val,
1184                                     accessSize, *pFlags);
1185         }
1186         *pFlags |= pFilter->flags;
1187         pFilter = pFilter->pNext;
1188     }
1189 
1190     portSyncSpinlockAcquire(pRegFilter->pRegFilterLock);
1191     pRegFilter->regFilterRefCnt--;
1192     if (pRegFilter->regFilterRefCnt == 0 && pRegFilter->bRegFilterNeedRemove)
1193     {
1194         // no other thread can be touching the list. remove invalid entries
1195         _gpuCleanRegisterFilterList(pRegFilter);
1196         pRegFilter->bRegFilterNeedRemove = NV_FALSE;
1197     }
1198     portSyncSpinlockRelease(pRegFilter->pRegFilterLock);
1199 }
1200 
1201 static REGISTER_FILTER *
_findGpuRegisterFilter(DEVICE_INDEX devIndex,NvU32 devInstance,NvU32 addr,REGISTER_FILTER * pFilter)1202 _findGpuRegisterFilter
1203 (
1204     DEVICE_INDEX     devIndex,
1205     NvU32            devInstance,
1206     NvU32            addr,
1207     REGISTER_FILTER *pFilter
1208 )
1209 {
1210     while (pFilter != NULL)
1211     {
1212         if (!(pFilter->flags & REGISTER_FILTER_FLAGS_INVALID) &&
1213             (devIndex == pFilter->devIndex) &&
1214             (devInstance == pFilter->devInstance) &&
1215             (addr >= pFilter->rangeStart) && (addr <= pFilter->rangeEnd))
1216         {
1217             break;
1218         }
1219 
1220         pFilter = pFilter->pNext;
1221     }
1222 
1223     return pFilter;
1224 }
1225 
1226 static NvBool
_gpuEnablePciMemSpaceAndCheckPmcBoot0Match(OBJGPU * pGpu)1227 _gpuEnablePciMemSpaceAndCheckPmcBoot0Match
1228 (
1229     OBJGPU *pGpu
1230 )
1231 {
1232     NvU16 VendorId;
1233     NvU16 DeviceId;
1234     NvU8  bus = gpuGetBus(pGpu);
1235     NvU8  device = gpuGetDevice(pGpu);
1236     NvU32 domain = gpuGetDomain(pGpu);
1237     void *Handle = osPciInitHandle(domain, bus, device, 0, &VendorId, &DeviceId);
1238     NvU32 Enabled = osPciReadDword(Handle, NV_CONFIG_PCI_NV_1);
1239     NvU32 pmcBoot0;
1240 
1241     // If Memory Spaced is not enabled, enable it
1242     if (DRF_VAL(_CONFIG, _PCI_NV_1, _MEMORY_SPACE, Enabled) != NV_CONFIG_PCI_NV_1_MEMORY_SPACE_ENABLED)
1243     {
1244         osPciWriteDword(Handle, NV_CONFIG_PCI_NV_1,
1245                         Enabled |
1246                         (DRF_DEF(_CONFIG, _PCI_NV_1, _MEMORY_SPACE, _ENABLED) |
1247                         DRF_DEF(_CONFIG, _PCI_NV_1, _BUS_MASTER, _ENABLED)));
1248     }
1249 
1250     // Check PMC_ENABLE to make sure that it matches
1251     pmcBoot0 = GPU_REG_RD32(pGpu, NV_PMC_BOOT_0);
1252     if (pmcBoot0 == pGpu->chipId0)
1253     {
1254        return NV_TRUE;
1255     }
1256 
1257     return NV_FALSE;
1258 }
1259 
1260 static NvU32
_regCheckReadFailure(OBJGPU * pGpu,NvU32 value)1261 _regCheckReadFailure
1262 (
1263     OBJGPU *pGpu,
1264     NvU32   value
1265 )
1266 {
1267     NvU32 flagsFailed;
1268     NvU32 reason = BAD_READ_UNKNOWN;
1269 
1270     if ((!pGpu->getProperty(pGpu, PDB_PROP_GPU_IN_PM_CODEPATH)) &&
1271         (!pGpu->getProperty(pGpu, PDB_PROP_GPU_IS_LOST)))
1272     {
1273         gpuSanityCheck(pGpu, GPU_SANITY_CHECK_FLAGS_ALL, &flagsFailed);
1274 
1275         // This is where we need to determine why we might be seeing this failure
1276         if (value == GPU_REG_VALUE_INVALID)
1277         {
1278             // Does PCI Space Match
1279             if (flagsFailed & GPU_SANITY_CHECK_FLAGS_PCI_SPACE_MATCH)
1280             {
1281                 reason = BAD_READ_GPU_OFF_BUS;
1282                 goto exit;
1283             }
1284 
1285             // Is Memory Spaced Enabled
1286             if (flagsFailed & GPU_SANITY_CHECK_FLAGS_PCI_MEM_SPACE_ENABLED)
1287             {
1288                 reason = BAD_READ_PCI_DEVICE_DISABLED;
1289 
1290                 if (!_gpuEnablePciMemSpaceAndCheckPmcBoot0Match(pGpu))
1291                 {
1292                     // We have been reset!
1293                     reason = BAD_READ_GPU_RESET;
1294                     goto exit;
1295                 }
1296             }
1297         }
1298 
1299         // Are we off by N
1300         if (flagsFailed & GPU_SANITY_CHECK_FLAGS_OFF_BY_N)
1301         {
1302             reason = BAD_READ_DWORD_SHIFT;
1303         }
1304     }
1305     else
1306     {
1307         reason = BAD_READ_LOW_POWER;
1308     }
1309 
1310 exit:
1311     return reason;
1312 }
1313 
1314 void
regCheckAndLogReadFailure(RegisterAccess * pRegisterAccess,NvU32 addr,NvU32 mask,NvU32 value)1315 regCheckAndLogReadFailure
1316 (
1317     RegisterAccess *pRegisterAccess,
1318     NvU32 addr,
1319     NvU32 mask,
1320     NvU32 value
1321 )
1322 {
1323     OBJGPU *pGpu = pRegisterAccess->pGpu;
1324     const NvU32 failureReason = _regCheckReadFailure(pGpu, value);
1325     PRmRC2BadRead2_RECORD pBadRead = NULL;
1326     OBJSYS *pSys = SYS_GET_INSTANCE();
1327 
1328     // Record a Journal Entry about this failure
1329     if (rcdbAllocNextJournalRec(SYS_GET_RCDB(pSys),
1330                                 (NVCD_RECORD **)&pBadRead,
1331                                 RmGroup,
1332                                 RmBadRead_V2,
1333                                 sizeof *pBadRead) == NV_OK)
1334     {
1335         rcdbSetCommonJournalRecord(pGpu, &pBadRead->common);
1336         pBadRead->MemorySpace = MEMORY_BAR0;
1337         pBadRead->Offset = addr;
1338         pBadRead->Mask = mask;
1339         pBadRead->Value = value;
1340         pBadRead->Reason = failureReason;
1341 
1342         // We are seeing some misreads in DVS runs.  Adding this so that we can get
1343         // stack traces of why this is happening
1344         if ((NV_DEBUG_BREAK_ATTRIBUTES_CRASH) &
1345             DRF_VAL(_DEBUG, _BREAK, _ATTRIBUTES, pSys->debugFlags))
1346         {
1347             osBugCheck(OS_BUG_CHECK_BUGCODE_INTERNAL_TEST);
1348         }
1349     }
1350 
1351     PORT_UNREFERENCED_VARIABLE(failureReason);
1352 }
1353 
1354 NvU32
regCheckRead032(RegisterAccess * pRegisterAccess,NvU32 addr,NvU32 mask,THREAD_STATE_NODE * pThreadState)1355 regCheckRead032
1356 (
1357     RegisterAccess    *pRegisterAccess,
1358     NvU32              addr,
1359     NvU32              mask,
1360     THREAD_STATE_NODE *pThreadState
1361 )
1362 {
1363     NvU32 returnValue;
1364     OBJGPU *pGpu = pRegisterAccess->pGpu;
1365 
1366     returnValue = GPU_REG_RD32_EX(pGpu, addr, pThreadState);
1367     if (returnValue & mask)
1368     {
1369         if (!API_GPU_IN_RESET_SANITY_CHECK(pGpu))
1370             regCheckAndLogReadFailure(pRegisterAccess, addr, mask, returnValue);
1371         returnValue = 0;
1372     }
1373 
1374     return returnValue;
1375 }
1376 
1377 #if GPU_REGISTER_ACCESS_DUMP
1378 
1379 NvU8
gpuRegRd08_dumpinfo(const char * func,const char * addrStr,const char * vreg,OBJGPU * pGpu,NvU32 addr)1380 gpuRegRd08_dumpinfo(const char *func, const char *addrStr, const char *vreg, OBJGPU *pGpu, NvU32 addr)
1381 {
1382     NvU8 val = REG_INST_RD08(pGpu, GPU, 0, addr);
1383     // filter out duplicate read
1384     static NvU32 prev_addr = 0;
1385     static NvU8  prev_val  = 0;
1386     if (addr != prev_addr || val != prev_val)
1387     {
1388         // filter out bar0 windows registers (NV_PRAMIN – range 0x007FFFFF:0x00700000 )
1389         if ((addr & 0xFFF00000) != 0x00700000)
1390         {
1391             NV_PRINTF(LEVEL_NOTICE,
1392                       "READ   func: %s, reg name: %s, addr: %08x, val: %02x\n",
1393                       func, addrStr, addr, val);
1394         }
1395         prev_addr = addr;
1396         prev_val = val;
1397     }
1398     return val;
1399 }
1400 
1401 NvU16
gpuRegRd16_dumpinfo(const char * func,const char * addrStr,const char * vreg,OBJGPU * pGpu,NvU32 addr)1402 gpuRegRd16_dumpinfo(const char *func, const char *addrStr, const char *vreg, OBJGPU *pGpu, NvU32 addr)
1403 {
1404     NvU16 val = REG_INST_RD16(pGpu, GPU, 0, addr);
1405     // filter out duplicate read
1406     static NvU32 prev_addr = 0;
1407     static NvU16 prev_val  = 0;
1408     if (addr != prev_addr || val != prev_val)
1409     {
1410         // filter out bar0 windows registers (NV_PRAMIN – range 0x007FFFFF:0x00700000 )
1411         if ((addr & 0xFFF00000) != 0x00700000)
1412         {
1413             NV_PRINTF(LEVEL_NOTICE,
1414                       "READ   func: %s, reg name: %s, addr: %08x, val: %04x\n",
1415                       func, addrStr, addr, val);
1416         }
1417         prev_addr = addr;
1418         prev_val = val;
1419     }
1420     return val;
1421 }
1422 
1423 NvU32
gpuRegRd32_dumpinfo(const char * func,const char * addrStr,const char * vreg,OBJGPU * pGpu,NvU32 addr)1424 gpuRegRd32_dumpinfo(const char *func, const char *addrStr, const char *vreg, OBJGPU *pGpu, NvU32 addr)
1425 {
1426     NvU32 val = REG_INST_RD32(pGpu, GPU, 0, addr);
1427     // filter out duplicate read
1428     static NvU32 prev_addr = 0;
1429     static NvU32 prev_val  = 0;
1430     if (addr != prev_addr || val != prev_val)
1431     {
1432         // filter out bar0 windows registers (NV_PRAMIN – range 0x007FFFFF:0x00700000 )
1433         if ((addr & 0xFFF00000) != 0x00700000)
1434         {
1435             NV_PRINTF(LEVEL_NOTICE,
1436                       "READ  %s func: %s, reg name: %s, addr: %08x, val: %08x\n",
1437                       vreg, func, addrStr, addr, val);
1438         }
1439         prev_addr = addr;
1440         prev_val = val;
1441     }
1442     return val;
1443 }
1444 
1445 void
gpuRegWr08_dumpinfo(const char * func,const char * addrStr,const char * vreg,OBJGPU * pGpu,NvU32 addr,NvV8 val)1446 gpuRegWr08_dumpinfo(const char *func, const char *addrStr, const char *vreg, OBJGPU *pGpu, NvU32 addr, NvV8 val)
1447 {
1448     // filter out bar0 windows registers (NV_PRAMIN – range 0x007FFFFF:0x00700000 )
1449     if ((addr & 0xFFF00000) != 0x00700000)
1450     {
1451         NV_PRINTF(LEVEL_NOTICE,
1452                  "WRITE  func: %s, reg name: %s, addr: %08x, val: %02x\n",
1453                  func, addrStr, addr, val);
1454     }
1455     REG_INST_WR08(pGpu, GPU, 0, addr, val);
1456 }
1457 
1458 void
gpuRegWr16_dumpinfo(const char * func,const char * addrStr,const char * vreg,OBJGPU * pGpu,NvU32 addr,NvV16 val)1459 gpuRegWr16_dumpinfo(const char *func, const char *addrStr, const char *vreg, OBJGPU *pGpu, NvU32 addr, NvV16 val)
1460 {
1461     // filter out bar0 windows registers (NV_PRAMIN – range 0x007FFFFF:0x00700000 )
1462     if ((addr & 0xFFF00000) != 0x00700000)
1463     {
1464         NV_PRINTF(LEVEL_NOTICE,
1465                   "WRITE  func: %s, reg name: %s, addr: %08x, val: %04x\n",
1466                   func, addrStr, addr, val);
1467     }
1468     REG_INST_WR16(pGpu, GPU, 0, addr, val);
1469 }
1470 
1471 void
gpuRegWr32_dumpinfo(const char * func,const char * addrStr,const char * vreg,OBJGPU * pGpu,NvU32 addr,NvV32 val)1472 gpuRegWr32_dumpinfo(const char *func, const char *addrStr, const char *vreg, OBJGPU *pGpu, NvU32 addr, NvV32 val)
1473 {
1474     // filter out bar0 windows registers (NV_PRAMIN – range 0x007FFFFF:0x00700000 )
1475     if ((addr & 0xFFF00000) != 0x00700000)
1476     {
1477         NV_PRINTF(LEVEL_NOTICE,
1478                   "WRITE %s func: %s, reg name: %s, addr: %08x, val: %08x\n",
1479                   vreg, func, addrStr, addr, val);
1480     }
1481     REG_INST_WR32(pGpu, GPU, 0, addr, val);
1482 }
1483 
1484 void
gpuRegWr32Uc_dumpinfo(const char * func,const char * addrStr,const char * vreg,OBJGPU * pGpu,NvU32 addr,NvV32 val)1485 gpuRegWr32Uc_dumpinfo(const char *func, const char *addrStr, const char *vreg, OBJGPU *pGpu, NvU32 addr, NvV32 val)
1486 {
1487     // filter out bar0 windows registers (NV_PRAMIN – range 0x007FFFFF:0x00700000 )
1488     if ((addr & 0xFFF00000) != 0x00700000)
1489     {
1490         NV_PRINTF(LEVEL_NOTICE,
1491                   "WRITE  func: %s, reg name: %s, addr: %08x, val: %08x\n",
1492                   func, addrStr, addr, val);
1493     }
1494     REG_INST_WR32_UC(pGpu, GPU, 0, addr, val);
1495 }
1496 
1497 #endif // GPU_REGISTER_ACCESS_DUMP
1498 
1499 /*!
1500  * @brief Do any sanity checks for the GPU's state before actually reading/writing to the chip.
1501  *
1502  * @param[in]  pGpu       OBJGPU pointer
1503  * @param[in]  addr       Address of the register to be sanity checked
1504  * @param[out] pRetVal    Default return value for read accesses incase of sanity check failure. Only for U032 hals.
1505  *
1506  * @returns NV_ERR_GPU_IN_FULLCHIP_RESET    if GPU is in reset
1507  *          NV_ERR_GPU_IS_LOST              if GPU is inaccessible
1508  *          NV_ERR_GPU_NOT_FULL_POWER       if GPU is not at full power AND
1509  *                                             GPU is not in resume codepath
1510  *                                             sim low power reg access is disabled
1511  *          NV_OK                           Otherwise
1512  */
1513 NV_STATUS
gpuSanityCheckRegisterAccess_IMPL(OBJGPU * pGpu,NvU32 addr,NvU32 * pRetVal)1514 gpuSanityCheckRegisterAccess_IMPL
1515 (
1516     OBJGPU     *pGpu,
1517     NvU32       addr,
1518     NvU32       *pRetVal
1519 )
1520 {
1521     NV_STATUS status = NV_OK;
1522     NvU32     retVal = ~0;
1523 
1524     if (API_GPU_IN_RESET_SANITY_CHECK(pGpu))
1525     {
1526         status = NV_ERR_GPU_IN_FULLCHIP_RESET;
1527         goto done;
1528     }
1529 
1530     if (!API_GPU_ATTACHED_SANITY_CHECK(pGpu))
1531     {
1532         status = NV_ERR_GPU_IS_LOST;
1533         goto done;
1534     }
1535 
1536     if ((status = gpuSanityCheckVirtRegAccess_HAL(pGpu, addr)) != NV_OK)
1537     {
1538         NV_PRINTF(LEVEL_ERROR, "Invalid register access on VF, addr: 0x%x\n", addr);
1539         osAssertFailed();
1540 
1541         // Return 0 to match with HW behavior
1542         retVal = 0;
1543         goto done;
1544     }
1545 
1546     //
1547     // Make sure the GPU is in full power or resuming.  When the OS has put the
1548     // GPU in suspend (i.e. any of the D3 variants) there's no guarantee the GPU is
1549     // accessible over PCI-E: the GPU may be completely powered off, the
1550     // upstream bridges may not be properly configured, etc.  Attempts to access
1551     // the GPU may then result in PCI-E errors and/or bugchecks.  For examples,
1552     // see Bugs 440565 and 479003.
1553     // On Mshybrid, the OS will make sure we are up and alive before calling
1554     // into the driver. So we can skip this check on MsHybrid.
1555     //
1556     // DO NOT IGNORE OR REMOVE THIS ASSERT.  It is a warning that improperly
1557     // written RM code further up the stack is trying to access a GPU which is
1558     // in suspend (i.e. low power).  Any entry points into the RM (especially
1559     // those between GPUs or for asynchronous callbacks) should always check
1560     // that the GPU is in full power via gpuIsGpuFullPower(), bailing out in the
1561     // appropriate manner when it returns NV_FALSE.
1562     //
1563     // If you are not an RM engineer and are encountering this assert, please
1564     // file a bug against the RM.
1565     //
1566     if ((gpuIsGpuFullPower(pGpu) == NV_FALSE)                        &&
1567         !IS_GPU_GC6_STATE_ENTERING(pGpu)                             &&
1568         !(IS_GPU_GC6_STATE_ENTERED(pGpu)
1569          )                                                           &&
1570         !pGpu->getProperty(pGpu, PDB_PROP_GPU_MSHYBRID_GC6_ACTIVE)   &&
1571         !pGpu->getProperty(pGpu, PDB_PROP_GPU_ENABLE_REG_ACCESS_IN_LOW_POWER_FOR_SIM_SRTEST) &&
1572         !pGpu->getProperty(pGpu, PDB_PROP_GPU_IN_PM_RESUME_CODEPATH))
1573     {
1574         DBG_BREAKPOINT();
1575         status = NV_ERR_GPU_NOT_FULL_POWER;
1576         goto done;
1577     }
1578 
1579     // TODO: More complete sanity checking
1580 
1581 done:
1582     // Assign the return value
1583     if ((status != NV_OK) && (pRetVal != NULL))
1584     {
1585         *pRetVal = retVal;
1586     }
1587     return status;
1588 }
1589 
1590 /**
1591  * @brief checks if the register offset is valid
1592  *
1593  * @param[in] pGpu
1594  * @param[in] offset
1595  *
1596  * @returns NV_OK if valid
1597  * @returns NV_ERR_INVALID_ARGUMENT if offset is too large for bar
1598  * @returns NV_ERR_INSUFFICIENT_PERMISSIONS if user is not authorized to access register
1599  */
1600 NV_STATUS
gpuValidateRegOffset_IMPL(OBJGPU * pGpu,NvU32 offset)1601 gpuValidateRegOffset_IMPL
1602 (
1603     OBJGPU *pGpu,
1604     NvU32   offset
1605 )
1606 {
1607     NvU64 maxBar0Size = pGpu->deviceMappings[0].gpuNvLength;
1608 
1609     // The register offset should be 4 bytes smaller than the max bar size
1610     if (offset > (maxBar0Size - 4))
1611     {
1612         return NV_ERR_INVALID_ARGUMENT;
1613     }
1614 
1615     if (!osIsAdministrator() &&
1616         !gpuGetUserRegisterAccessPermissions(pGpu, offset))
1617     {
1618         NV_PRINTF(LEVEL_ERROR,
1619                   "User does not have permission to access register offset 0x%x\n",
1620                   offset);
1621         return NV_ERR_INSUFFICIENT_PERMISSIONS;
1622     }
1623 
1624     return NV_OK;
1625 }
1626 
1627 /*!
1628  * @brief Verify existence function.
1629  *
1630  * @param[in] pGpu
1631  *
1632  * @returns NV_OK if GPU is still accessible
1633  *          NV_ERR_INVALID_STATE if GPU is inaccessible
1634  */
1635 NV_STATUS
gpuVerifyExistence_IMPL(OBJGPU * pGpu)1636 gpuVerifyExistence_IMPL
1637 (
1638     OBJGPU *pGpu
1639 )
1640 {
1641     NvU32 regVal = GPU_REG_RD32(pGpu, NV_PMC_BOOT_0);
1642 
1643     if (regVal != pGpu->chipId0)
1644     {
1645         osHandleGpuLost(pGpu);
1646         regVal = GPU_REG_RD32(pGpu, NV_PMC_BOOT_0);
1647         if (regVal != pGpu->chipId0)
1648         {
1649             return NV_ERR_GPU_IS_LOST;
1650         }
1651     }
1652 
1653     return NV_OK;
1654 }
1655 
1656 /*!
1657  * @brief Perform a sanity check on a register read value
1658  * Starts with gpu-independent check, then calls into HAL for specific cases
1659  *
1660  * @param[in]       pGpu        GPU object pointer
1661  * @param[in]       addr        Value address
1662  * @param[in]       size        Access size
1663  * @param[in/out]   pValue      Value to sanity check
1664  */
1665 NV_STATUS
gpuSanityCheckRegRead_IMPL(OBJGPU * pGpu,NvU32 addr,NvU32 size,void * pValue)1666 gpuSanityCheckRegRead_IMPL
1667 (
1668     OBJGPU *pGpu,
1669     NvU32 addr,
1670     NvU32 size,
1671     void *pValue
1672 )
1673 {
1674     NvU8       *pValue8;
1675     NvU16      *pValue16;
1676     NvU32      *pValue32;
1677     NvU32       value;
1678 
1679     switch (size)
1680     {
1681         case 8:
1682             {
1683                 pValue8 = ((NvU8 *) pValue);
1684                 if (*pValue8 == (NvU8) (~0))
1685                 {
1686                     //
1687                     // The result looks suspicious, let's check if the GPU is still attached.
1688                     //
1689                     NvU32 testValue = osGpuReadReg032(pGpu, NV_PMC_BOOT_0);
1690                     if (testValue == GPU_REG_VALUE_INVALID)
1691                     {
1692                         osHandleGpuLost(pGpu);
1693                         *pValue8 = osGpuReadReg008(pGpu, addr);
1694                     }
1695                 }
1696                 break;
1697             }
1698         case 16:
1699             {
1700                 pValue16 = ((NvU16 *) pValue);
1701                 if (*pValue16 == (NvU16) (~0))
1702                 {
1703                     //
1704                     // The result looks suspicious, let's check if the GPU is still attached.
1705                     //
1706                     NvU32 testValue = osGpuReadReg032(pGpu, NV_PMC_BOOT_0);
1707                     if (testValue == GPU_REG_VALUE_INVALID)
1708                     {
1709                         osHandleGpuLost(pGpu);
1710                         *pValue16 = osGpuReadReg016(pGpu, addr);
1711                     }
1712                 }
1713                 break;
1714             }
1715         case 32:
1716             {
1717                 pValue32 = ((NvU32 *) pValue);
1718                 if (*pValue32 == (NvU32) (~0))
1719                 {
1720                     //
1721                     // The result looks suspicious, let's check if the GPU is still attached.
1722                     //
1723                     NvU32 testValue = osGpuReadReg032(pGpu, NV_PMC_BOOT_0);
1724                     if (testValue == GPU_REG_VALUE_INVALID)
1725                     {
1726                         osHandleGpuLost(pGpu);
1727                         *pValue32 = osGpuReadReg032(pGpu, addr);
1728                     }
1729                 }
1730 
1731                 value = *((NvU32 *)pValue);
1732 
1733                 //
1734                 // HW will return 0xbad in the upper 3 nibbles
1735                 // when there is a possible issue.
1736                 //
1737                 if ((value & GPU_READ_PRI_ERROR_MASK) == GPU_READ_PRI_ERROR_CODE)
1738                 {
1739                     gpuHandleSanityCheckRegReadError_HAL(pGpu, addr, value);
1740                 }
1741                 break;
1742             }
1743         default:
1744             {
1745                 NV_ASSERT_FAILED("Invalid access size");
1746                 break;
1747             }
1748     }
1749 
1750     return NV_OK;
1751 }
1752 
1753 
swbcaprtConstruct_IMPL(SwBcAperture * pAperture,IoAperture * pApertures,NvU32 numApertures)1754 NV_STATUS swbcaprtConstruct_IMPL
1755 (
1756     SwBcAperture      *pAperture,
1757     IoAperture        *pApertures,
1758     NvU32              numApertures
1759 )
1760 {
1761     NV_ASSERT_OR_RETURN(numApertures != 0, NV_ERR_INVALID_ARGUMENT);
1762 
1763     pAperture->pApertures = pApertures;
1764     pAperture->numApertures = numApertures;
1765 
1766     return NV_OK;
1767 }
1768 
1769 NvU8
swbcaprtReadReg08_IMPL(SwBcAperture * pAperture,NvU32 addr)1770 swbcaprtReadReg08_IMPL
1771 (
1772     SwBcAperture *pAperture,
1773     NvU32         addr
1774 )
1775 {
1776     NvU8 val = REG_RD08(&pAperture->pApertures[0], addr);
1777 
1778 #if defined(DEBUG)
1779     NvU32 i;
1780     for (i = 1; i < pAperture->numApertures; i++)
1781         NV_ASSERT(REG_RD08(&pAperture->pApertures[i], addr) == val);
1782 #endif // defined(DEBUG)
1783 
1784     return val;
1785 }
1786 
1787 NvU16
swbcaprtReadReg16_IMPL(SwBcAperture * pAperture,NvU32 addr)1788 swbcaprtReadReg16_IMPL
1789 (
1790     SwBcAperture *pAperture,
1791     NvU32         addr
1792 )
1793 {
1794     NvU16 val = REG_RD16(&pAperture->pApertures[0], addr);
1795 
1796 #if defined(DEBUG)
1797     NvU32 i;
1798     for (i = 1; i < pAperture->numApertures; i++)
1799         NV_ASSERT(REG_RD16(&pAperture->pApertures[i], addr) == val);
1800 #endif // defined(DEBUG)
1801 
1802     return val;
1803 }
1804 
1805 NvU32
swbcaprtReadReg32_IMPL(SwBcAperture * pAperture,NvU32 addr)1806 swbcaprtReadReg32_IMPL
1807 (
1808     SwBcAperture *pAperture,
1809     NvU32         addr
1810 )
1811 {
1812     NvU32 val = REG_RD32(&pAperture->pApertures[0], addr);
1813 
1814 #if defined(DEBUG)
1815     NvU32 i;
1816     for (i = 1; i < pAperture->numApertures; i++)
1817         NV_ASSERT(REG_RD32(&pAperture->pApertures[i], addr) == val);
1818 #endif // defined(DEBUG)
1819 
1820     return val;
1821 }
1822 
1823 void
swbcaprtWriteReg08_IMPL(SwBcAperture * pAperture,NvU32 addr,NvV8 value)1824 swbcaprtWriteReg08_IMPL
1825 (
1826     SwBcAperture *pAperture,
1827     NvU32         addr,
1828     NvV8          value
1829 )
1830 {
1831     NvU32 i;
1832 
1833     for (i = 0; i < pAperture->numApertures; i++)
1834         REG_WR08(&pAperture->pApertures[i], addr, value);
1835 }
1836 
1837 void
swbcaprtWriteReg16_IMPL(SwBcAperture * pAperture,NvU32 addr,NvV16 value)1838 swbcaprtWriteReg16_IMPL
1839 (
1840     SwBcAperture *pAperture,
1841     NvU32         addr,
1842     NvV16         value
1843 )
1844 {
1845     NvU32 i;
1846 
1847     for (i = 0; i < pAperture->numApertures; i++)
1848         REG_WR16(&pAperture->pApertures[i], addr, value);
1849 }
1850 
1851 void
swbcaprtWriteReg32_IMPL(SwBcAperture * pAperture,NvU32 addr,NvV32 value)1852 swbcaprtWriteReg32_IMPL
1853 (
1854     SwBcAperture *pAperture,
1855     NvU32         addr,
1856     NvV32         value
1857 )
1858 {
1859     NvU32 i;
1860 
1861     for (i = 0; i < pAperture->numApertures; i++)
1862         REG_WR32(&pAperture->pApertures[i], addr, value);
1863 }
1864 
1865 void
swbcaprtWriteReg32Uc_IMPL(SwBcAperture * pAperture,NvU32 addr,NvV32 value)1866 swbcaprtWriteReg32Uc_IMPL
1867 (
1868     SwBcAperture *pAperture,
1869     NvU32         addr,
1870     NvV32         value
1871 )
1872 {
1873     NvU32 i;
1874 
1875     for (i = 0; i < pAperture->numApertures; i++)
1876         REG_WR32_UC(&pAperture->pApertures[i], addr, value);
1877 }
1878 
1879 NvBool
swbcaprtIsRegValid_IMPL(SwBcAperture * pAperture,NvU32 addr)1880 swbcaprtIsRegValid_IMPL
1881 (
1882     SwBcAperture *pAperture,
1883     NvU32         addr
1884 )
1885 {
1886 
1887     NvU32 i;
1888 
1889     for (i = 0; i < pAperture->numApertures; i++)
1890     {
1891         if (!REG_VALID(&pAperture->pApertures[i], addr))
1892             return NV_FALSE;
1893     }
1894 
1895     return NV_TRUE;
1896 }
1897