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