1 /*
2 * SPDX-FileCopyrightText: Copyright (c) 1993-2021 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 "gpu/gpu.h"
25 #include "gpu/gpu_device_mapping.h"
26 #include "core/thread_state.h"
27 #include "nv_ref.h"
28
29 /**
30 * @brief Finds the device mapping matching the specified address and device index
31 *
32 * @param[in] pGpu
33 * @param[in] deviceIndex device specific device enum (DEVICE_INDEX_*)
34 * @param[in] addr device register address
35 *
36 * @returns matching mapping, or NULL if not found.
37 */
38 static DEVICE_MAPPING *
_gpuFindDeviceMapping(OBJGPU * pGpu,DEVICE_INDEX deviceIndex,NvU32 instance)39 _gpuFindDeviceMapping
40 (
41 OBJGPU *pGpu,
42 DEVICE_INDEX deviceIndex,
43 NvU32 instance
44 )
45 {
46 NvU32 i;
47 NvU32 devId = 0;
48 DEVICE_ID_MAPPING *deviceIdMapping;
49 NvU32 numDeviceIDs;
50
51 numDeviceIDs = gpuGetDeviceIDList_HAL(pGpu, &deviceIdMapping);
52
53 // Find the devID that matches the requested device index
54 for (i = 0; i < numDeviceIDs; i++)
55 {
56 if (deviceIdMapping[i].deviceIndex == deviceIndex)
57 {
58 devId = deviceIdMapping[i].devId;
59 break;
60 }
61 }
62
63 if (devId == 0)
64 {
65 // For discrete GPU, just return BAR0 mapping
66 if (deviceIndex == DEVICE_INDEX_GPU)
67 {
68 return &pGpu->deviceMappings[0];
69 }
70 else
71 {
72 NV_PRINTF(LEVEL_ERROR,
73 "Could not find mapping for deviceIndex=%d\n",
74 deviceIndex);
75 return NULL;
76 }
77 }
78 return gpuGetDeviceMappingFromDeviceID(pGpu, devId, instance);
79 }
80
81 DEVICE_MAPPING *
gpuGetDeviceMapping_IMPL(OBJGPU * pGpu,DEVICE_INDEX deviceIndex,NvU32 instance)82 gpuGetDeviceMapping_IMPL
83 (
84 OBJGPU *pGpu,
85 DEVICE_INDEX deviceIndex,
86 NvU32 instance
87 )
88 {
89 // Fast lookup path for first instance of a device
90 if ((deviceIndex < DEVICE_INDEX_MAX) && (instance == 0))
91 {
92 if (!pGpu->pDeviceMappingsByDeviceInstance[deviceIndex])
93 {
94 pGpu->pDeviceMappingsByDeviceInstance[deviceIndex] = _gpuFindDeviceMapping(pGpu, deviceIndex, instance);
95 }
96 return pGpu->pDeviceMappingsByDeviceInstance[deviceIndex];
97 }
98
99 return _gpuFindDeviceMapping(pGpu, deviceIndex, instance);
100 }
101
102 /**
103 * @brief Returns the device mapping matching the specified device ID from
104 * project relocation table
105 *
106 * @param[in] pGpu OBJGPU pointer
107 * @param[in] deviceId device ID from project relocation table
108 * @param[in] instance instance of the particular device ID
109 *
110 * @returns matching mapping, or NULL if not found.
111 */
112
113 DEVICE_MAPPING *
gpuGetDeviceMappingFromDeviceID_IMPL(OBJGPU * pGpu,NvU32 deviceId,NvU32 instance)114 gpuGetDeviceMappingFromDeviceID_IMPL
115 (
116 OBJGPU *pGpu,
117 NvU32 deviceId,
118 NvU32 instance
119 )
120 {
121 NvU32 i;
122
123 //
124 // For SOC, walk the list of devices to find the device/instance requested.
125 // For GPU (legacy), only NV_DEVID_GPU(0) is expected & allowed
126 //
127 if (pGpu->bIsSOC)
128 {
129 for (i = 0; i < pGpu->gpuDeviceMapCount; i++)
130 {
131 if (pGpu->deviceMappings[i].gpuDeviceEnum == deviceId)
132 {
133 // Find the Nth instance of the requested device
134 if (instance)
135 instance--;
136 else
137 return &pGpu->deviceMappings[i];
138 }
139 }
140
141 NV_PRINTF(LEVEL_ERROR, "Could not find mapping for deviceId=%d\n",
142 deviceId);
143 }
144 else
145 {
146 // For GPU, always assume NV_DEVID_GPU instance 0.
147 NV_ASSERT(instance == 0);
148 NV_ASSERT(pGpu->gpuDeviceMapCount == 1);
149
150 return &pGpu->deviceMappings[0];
151 }
152
153 return NULL;
154 }
155
_gpuCheckIsBar0OffByN(OBJGPU * pGpu)156 static NvBool _gpuCheckIsBar0OffByN(OBJGPU *pGpu)
157 {
158 NvU32 i, pmcBoot0;
159
160 // Check to see if we can find PMC_BOOT_0
161 for (i = 0; i < 20; i++)
162 {
163 pmcBoot0 = GPU_REG_RD32(pGpu, NV_PMC_BOOT_0 + (i * 4));
164 if (pmcBoot0 == pGpu->chipId0)
165 {
166 break;
167 }
168 }
169
170 if ((i != 0) && (i != 20))
171 {
172 // We are off by N
173 return NV_TRUE;
174 }
175
176 // Everything looks ok
177 return NV_FALSE;
178 }
179
_gpuCheckDoesPciSpaceMatch(OBJGPU * pGpu)180 static NvBool _gpuCheckDoesPciSpaceMatch(OBJGPU *pGpu)
181 {
182 NvU16 VendorId;
183 NvU16 DeviceId;
184 NvU8 bus = gpuGetBus(pGpu);
185 NvU8 device = gpuGetDevice(pGpu);
186 NvU32 domain = gpuGetDomain(pGpu);
187
188 osPciInitHandle(domain, bus, device, 0, &VendorId, &DeviceId);
189 if ((DeviceId == 0xFFFF) ||
190 (VendorId != 0x10DE))
191 {
192 return NV_FALSE;
193 }
194
195 return NV_TRUE;
196 }
197
_gpuCheckIsPciMemSpaceEnabled(OBJGPU * pGpu)198 static NvBool _gpuCheckIsPciMemSpaceEnabled(OBJGPU *pGpu)
199 {
200 NvU16 VendorId;
201 NvU16 DeviceId;
202 NvU8 bus = gpuGetBus(pGpu);
203 NvU8 device = gpuGetDevice(pGpu);
204 NvU32 domain = gpuGetDomain(pGpu);
205 void *Handle = osPciInitHandle(domain, bus, device, 0, &VendorId, &DeviceId);
206 NvU32 Enabled = osPciReadDword(Handle, NV_CONFIG_PCI_NV_1);
207
208 // Is Memory Spaced Enabled
209 if (DRF_VAL(_CONFIG, _PCI_NV_1, _MEMORY_SPACE, Enabled) != NV_CONFIG_PCI_NV_1_MEMORY_SPACE_ENABLED)
210 {
211 return NV_FALSE;
212 }
213
214 return NV_TRUE;
215 }
216
gpuSanityCheck_IMPL(OBJGPU * pGpu,NvU32 flags,NvU32 * pFlagsFailed)217 NV_STATUS gpuSanityCheck_IMPL
218 (
219 OBJGPU *pGpu,
220 NvU32 flags,
221 NvU32 *pFlagsFailed
222 )
223 {
224 NV_STATUS rmStatus = NV_OK;
225 NvU32 flagsFailed = GPU_SANITY_CHECK_FLAGS_NONE;
226 THREAD_STATE_NODE *pThreadNode = NULL;
227
228 if (pFlagsFailed != NULL)
229 {
230 *pFlagsFailed = GPU_SANITY_CHECK_FLAGS_NONE;
231 }
232
233 if (pGpu->bIsSOC)
234 {
235 flags &= ~(
236 GPU_SANITY_CHECK_FLAGS_BOOT_0 |
237 GPU_SANITY_CHECK_FLAGS_OFF_BY_N |
238 GPU_SANITY_CHECK_FLAGS_PCI_SPACE_MATCH |
239 GPU_SANITY_CHECK_FLAGS_PCI_MEM_SPACE_ENABLED |
240 GPU_SANITY_CHECK_FLAGS_FB);
241
242 }
243
244 //
245 // Check to make sure the lock is held for this thread as the underlying
246 // functions can touch state and lists that expect exclusive access.
247 //
248 rmStatus = threadStateGetCurrent(&pThreadNode, pGpu);
249 if (rmStatus != NV_OK)
250 {
251 return rmStatus;
252 }
253 if (pThreadNode->flags & THREAD_STATE_FLAGS_IS_ISR_LOCKLESS)
254 {
255 return NV_ERR_NOT_SUPPORTED;
256 }
257
258 // Check to make sure we are powered on first
259 if (gpuIsGpuFullPower(pGpu) == NV_FALSE)
260 {
261 NV_ASSERT(0);
262 return NV_ERR_GPU_NOT_FULL_POWER;
263 }
264
265 if (flags & GPU_SANITY_CHECK_FLAGS_BOOT_0)
266 {
267 //
268 // When GPU is in reset reg reads will return 0xFFFFFFFF.
269 // Without this check RM would keep hitting assert during TDR recovery.
270 //
271 if (!API_GPU_IN_RESET_SANITY_CHECK(pGpu))
272 {
273 NvU32 pmcBoot0 = GPU_REG_RD32(pGpu, NV_PMC_BOOT_0);
274 if (pmcBoot0 != pGpu->chipId0)
275 {
276 flagsFailed |= GPU_SANITY_CHECK_FLAGS_BOOT_0;
277 NV_ASSERT(0);
278 }
279 }
280 }
281
282 if (flags & GPU_SANITY_CHECK_FLAGS_OFF_BY_N)
283 {
284 if (_gpuCheckIsBar0OffByN(pGpu))
285 {
286 flagsFailed |= GPU_SANITY_CHECK_FLAGS_OFF_BY_N;
287 NV_ASSERT(0);
288 }
289 }
290
291 if (flags & GPU_SANITY_CHECK_FLAGS_PCI_SPACE_MATCH)
292 {
293 if (!_gpuCheckDoesPciSpaceMatch(pGpu))
294 {
295 flagsFailed |= GPU_SANITY_CHECK_FLAGS_PCI_SPACE_MATCH;
296 NV_ASSERT(0);
297 }
298 }
299
300 if (flags & GPU_SANITY_CHECK_FLAGS_PCI_MEM_SPACE_ENABLED)
301 {
302 if (!_gpuCheckIsPciMemSpaceEnabled(pGpu))
303 {
304 flagsFailed |= GPU_SANITY_CHECK_FLAGS_PCI_MEM_SPACE_ENABLED;
305 NV_ASSERT(0);
306 }
307 }
308
309 if (flags & GPU_SANITY_CHECK_FLAGS_FB)
310 {
311 if (!gpuIsGpuFullPower(pGpu))
312 {
313 NV_ASSERT(0);
314 }
315 }
316
317 if (flagsFailed != GPU_SANITY_CHECK_FLAGS_NONE)
318 {
319 rmStatus = NV_ERR_GENERIC;
320 NV_PRINTF(LEVEL_ERROR, "Failed test flags: 0x%x\n", flagsFailed);
321 }
322
323 if (pFlagsFailed != NULL)
324 {
325 *pFlagsFailed = flagsFailed;
326 }
327
328 return rmStatus;
329 }
330