IntelSiliconPkg/dsc: Add CacheMaintenanceLib.
[mirror_edk2.git] / IntelSiliconPkg / IntelVTdDxe / VtdReg.c
CommitLineData
c049fc99
JY
1/** @file\r
2\r
3 Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>\r
4 This program and the accompanying materials\r
5 are licensed and made available under the terms and conditions of the BSD License\r
6 which accompanies this distribution. The full text of the license may be found at\r
7 http://opensource.org/licenses/bsd-license.php.\r
8\r
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
11\r
12**/\r
13\r
14#include "DmaProtection.h"\r
15\r
16UINT64 mVtdHostAddressWidthMask;\r
17UINTN mVtdUnitNumber;\r
18VTD_UNIT_INFORMATION *mVtdUnitInformation;\r
19\r
20BOOLEAN mVtdEnabled;\r
21\r
22/**\r
23 Invalid VTd global IOTLB.\r
24\r
25 @param[in] VtdIndex The index of VTd engine.\r
26\r
27 @retval EFI_SUCCESS VTd global IOTLB is invalidated.\r
28 @retval EFI_DEVICE_ERROR VTd global IOTLB is not invalidated.\r
29**/\r
30EFI_STATUS\r
31InvalidateVtdIOTLBGlobal (\r
32 IN UINTN VtdIndex\r
33 )\r
34{\r
35 UINT64 Reg64;\r
36 UINT32 Reg32;\r
37\r
38 if (!mVtdEnabled) {\r
39 return EFI_SUCCESS;\r
40 }\r
41\r
42 DEBUG((DEBUG_VERBOSE, "InvalidateVtdIOTLBGlobal(%d)\n", VtdIndex));\r
43\r
44 AsmWbinvd();\r
45\r
46 //\r
47 // Write Buffer Flush before invalidation\r
48 //\r
49 Reg32 = MmioRead32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_CAP_REG);\r
50 if ((Reg32 & B_CAP_REG_RWBF) != 0) {\r
51 MmioWrite32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_GCMD_REG, B_GMCD_REG_WBF);\r
52 }\r
53\r
54 //\r
55 // Invalidate the context cache\r
56 //\r
57 Reg64 = MmioRead64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_CCMD_REG);\r
58 if ((Reg64 & B_CCMD_REG_ICC) != 0) {\r
59 DEBUG ((DEBUG_ERROR,"ERROR: InvalidateVtdIOTLBGlobal: B_CCMD_REG_ICC is set for VTD(%d)\n",VtdIndex));\r
60 return EFI_DEVICE_ERROR;\r
61 }\r
62\r
63 Reg64 &= ((~B_CCMD_REG_ICC) & (~B_CCMD_REG_CIRG_MASK));\r
64 Reg64 |= (B_CCMD_REG_ICC | V_CCMD_REG_CIRG_GLOBAL);\r
65 MmioWrite64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_CCMD_REG, Reg64);\r
66\r
67 do {\r
68 Reg64 = MmioRead64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_CCMD_REG);\r
69 } while ((Reg64 & B_CCMD_REG_ICC) != 0);\r
70\r
71 //\r
72 // Invalidate the IOTLB cache\r
73 //\r
74\r
75 Reg64 = MmioRead64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + (mVtdUnitInformation[VtdIndex].ECapReg.Bits.IRO * 16) + R_IOTLB_REG);\r
76 if ((Reg64 & B_IOTLB_REG_IVT) != 0) {\r
77 DEBUG ((DEBUG_ERROR,"ERROR: InvalidateVtdIOTLBGlobal: B_IOTLB_REG_IVT is set for VTD(%d)\n", VtdIndex));\r
78 return EFI_DEVICE_ERROR;\r
79 }\r
80\r
81 Reg64 &= ((~B_IOTLB_REG_IVT) & (~B_IOTLB_REG_IIRG_MASK));\r
82 Reg64 |= (B_IOTLB_REG_IVT | V_IOTLB_REG_IIRG_GLOBAL);\r
83 MmioWrite64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + (mVtdUnitInformation[VtdIndex].ECapReg.Bits.IRO * 16) + R_IOTLB_REG, Reg64);\r
84\r
85 do {\r
86 Reg64 = MmioRead64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + (mVtdUnitInformation[VtdIndex].ECapReg.Bits.IRO * 16) + R_IOTLB_REG);\r
87 } while ((Reg64 & B_IOTLB_REG_IVT) != 0);\r
88\r
89 //\r
90 // Disable VTd\r
91 //\r
92 MmioWrite32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_GCMD_REG, B_GMCD_REG_SRTP);\r
93 do {\r
94 Reg32 = MmioRead32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_GSTS_REG);\r
95 } while((Reg32 & B_GSTS_REG_RTPS) == 0);\r
96\r
97 //\r
98 // Enable VTd\r
99 //\r
100 MmioWrite32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_GCMD_REG, B_GMCD_REG_TE);\r
101 do {\r
102 Reg32 = MmioRead32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_GSTS_REG);\r
103 } while ((Reg32 & B_GSTS_REG_TE) == 0);\r
104\r
105 return EFI_SUCCESS;\r
106}\r
107\r
108/**\r
109 Invalid VTd IOTLB domain.\r
110\r
111 @param[in] VtdIndex The index of VTd engine.\r
112 @param[in] DomainIdentifier The domain ID of the source.\r
113\r
114 @retval EFI_SUCCESS VTd IOTLB domain is invalidated.\r
115 @retval EFI_DEVICE_ERROR VTd IOTLB domain is not invalidated.\r
116**/\r
117EFI_STATUS\r
118InvalidateVtdIOTLBDomain (\r
119 IN UINTN VtdIndex,\r
120 IN UINT16 DomainIdentifier\r
121 )\r
122{\r
123 UINT64 Reg64;\r
124\r
125 if (!mVtdEnabled) {\r
126 return EFI_SUCCESS;\r
127 }\r
128\r
129 DEBUG((DEBUG_VERBOSE, "InvalidateVtdIOTLBDomain(%d): 0x%016lx (0x%04x)\n", VtdIndex, DomainIdentifier));\r
130\r
131 //\r
132 // Invalidate the context cache\r
133 //\r
134 Reg64 = MmioRead64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_CCMD_REG);\r
135 if ((Reg64 & B_CCMD_REG_ICC) != 0) {\r
136 DEBUG ((DEBUG_ERROR,"ERROR: InvalidateVtdIOTLBDomain: B_CCMD_REG_ICC is set for VTD(%d)\n",VtdIndex));\r
137 return EFI_DEVICE_ERROR;\r
138 }\r
139\r
140 Reg64 &= ((~B_CCMD_REG_ICC) & (~B_CCMD_REG_CIRG_MASK));\r
141 Reg64 |= (B_CCMD_REG_ICC | V_CCMD_REG_CIRG_DOMAIN);\r
142 Reg64 |= (B_CCMD_REG_ICC | V_CCMD_REG_CIRG_DOMAIN);\r
143 MmioWrite64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_CCMD_REG, Reg64);\r
144\r
145 do {\r
146 Reg64 = MmioRead64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_CCMD_REG);\r
147 } while ((Reg64 & B_CCMD_REG_ICC) != 0);\r
148\r
149 //\r
150 // Invalidate the IOTLB cache\r
151 //\r
152\r
153 Reg64 = MmioRead64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + (mVtdUnitInformation[VtdIndex].ECapReg.Bits.IRO * 16) + R_IOTLB_REG);\r
154 if ((Reg64 & B_IOTLB_REG_IVT) != 0) {\r
155 DEBUG ((DEBUG_ERROR,"ERROR: InvalidateVtdIOTLBDomain: B_IOTLB_REG_IVT is set for VTD(%d)\n", VtdIndex));\r
156 return EFI_DEVICE_ERROR;\r
157 }\r
158\r
159 Reg64 &= ((~B_IOTLB_REG_IVT) & (~B_IOTLB_REG_IIRG_MASK));\r
160 Reg64 |= (B_IOTLB_REG_IVT | V_IOTLB_REG_IIRG_DOMAIN);\r
f5046945 161 Reg64 |= LShiftU64 (DomainIdentifier, 32);\r
c049fc99
JY
162 MmioWrite64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + (mVtdUnitInformation[VtdIndex].ECapReg.Bits.IRO * 16) + R_IOTLB_REG, Reg64);\r
163\r
164 do {\r
165 Reg64 = MmioRead64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + (mVtdUnitInformation[VtdIndex].ECapReg.Bits.IRO * 16) + R_IOTLB_REG);\r
166 } while ((Reg64 & B_IOTLB_REG_IVT) != 0);\r
167\r
168 return EFI_SUCCESS;\r
169}\r
170\r
171/**\r
172 Invalid VTd IOTLB page.\r
173\r
174 @param[in] VtdIndex The index of VTd engine.\r
175 @param[in] Address The address of IOTLB page.\r
176 @param[in] AddressMode The address mode of IOTLB page.\r
177 @param[in] DomainIdentifier The domain ID of the source.\r
178\r
179 @retval EFI_SUCCESS VTd IOTLB page is invalidated.\r
180 @retval EFI_DEVICE_ERROR VTd IOTLB page is not invalidated.\r
181**/\r
182EFI_STATUS\r
183InvalidateVtdIOTLBPage (\r
184 IN UINTN VtdIndex,\r
185 IN UINT64 Address,\r
186 IN UINT8 AddressMode,\r
187 IN UINT16 DomainIdentifier\r
188 )\r
189{\r
190 UINT64 Reg64;\r
191 UINT64 Data64;\r
192\r
193 if (!mVtdEnabled) {\r
194 return EFI_SUCCESS;\r
195 }\r
196\r
197 DEBUG((DEBUG_VERBOSE, "InvalidateVtdIOTLBPage(%d): 0x%016lx (0x%02x)\n", VtdIndex, Address, AddressMode));\r
198\r
199 if (mVtdUnitInformation[VtdIndex].CapReg.Bits.PSI != 0) {\r
200 Reg64 = MmioRead64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + (mVtdUnitInformation[VtdIndex].ECapReg.Bits.IRO * 16) + R_IOTLB_REG);\r
201 if ((Reg64 & B_IOTLB_REG_IVT) != 0) {\r
202 DEBUG ((DEBUG_ERROR,"ERROR: InvalidateVtdIOTLBPage: B_IOTLB_REG_IVT is set for VTD(%d)\n", VtdIndex));\r
203 return EFI_DEVICE_ERROR;\r
204 }\r
205\r
206 Data64 = Address | AddressMode;\r
207 MmioWrite64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + (mVtdUnitInformation[VtdIndex].ECapReg.Bits.IRO * 16) + R_IVA_REG, Data64);\r
208\r
209 Reg64 &= ((~B_IOTLB_REG_IVT) & (~B_IOTLB_REG_IIRG_MASK));\r
210 Reg64 |= (B_IOTLB_REG_IVT | V_IOTLB_REG_IIRG_PAGE);\r
211 Reg64 |= LShiftU64 (DomainIdentifier, 32);\r
212 MmioWrite64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + (mVtdUnitInformation[VtdIndex].ECapReg.Bits.IRO * 16) + R_IOTLB_REG, Reg64);\r
213\r
214 do {\r
215 Reg64 = MmioRead64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + (mVtdUnitInformation[VtdIndex].ECapReg.Bits.IRO * 16) + R_IOTLB_REG);\r
216 } while ((Reg64 & B_IOTLB_REG_IVT) != 0);\r
217 } else {\r
218 InvalidateVtdIOTLBGlobal (VtdIndex);\r
219 }\r
220\r
221 return EFI_SUCCESS;\r
222}\r
223\r
224/**\r
225 Prepare VTD configuration.\r
226**/\r
227VOID\r
228PrepareVtdConfig (\r
229 VOID\r
230 )\r
231{\r
232 UINTN Index;\r
233 UINTN DomainNumber;\r
234\r
235 for (Index = 0; Index < mVtdUnitNumber; Index++) {\r
236 DEBUG ((DEBUG_INFO, "Dump VTd Capability (%d)\n", Index));\r
237 mVtdUnitInformation[Index].CapReg.Uint64 = MmioRead64 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_CAP_REG);\r
238 DumpVtdCapRegs (&mVtdUnitInformation[Index].CapReg);\r
239 mVtdUnitInformation[Index].ECapReg.Uint64 = MmioRead64 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_ECAP_REG);\r
240 DumpVtdECapRegs (&mVtdUnitInformation[Index].ECapReg);\r
241\r
242 if ((mVtdUnitInformation[Index].CapReg.Bits.SLLPS & BIT0) == 0) {\r
243 DEBUG((DEBUG_WARN, "!!!! 2MB super page is not supported on VTD %d !!!!\n", Index));\r
244 }\r
245 if ((mVtdUnitInformation[Index].CapReg.Bits.SAGAW & BIT2) == 0) {\r
246 DEBUG((DEBUG_ERROR, "!!!! 4-level page-table is not supported on VTD %d !!!!\n", Index));\r
247 return ;\r
248 }\r
249\r
250 DomainNumber = (UINTN)1 << (UINT8)((UINTN)mVtdUnitInformation[Index].CapReg.Bits.ND * 2 + 4);\r
251 if (mVtdUnitInformation[Index].PciDeviceInfo.PciDescriptorNumber >= DomainNumber) {\r
252 DEBUG((DEBUG_ERROR, "!!!! Pci device Number(0x%x) >= DomainNumber(0x%x) !!!!\n", mVtdUnitInformation[Index].PciDeviceInfo.PciDescriptorNumber, DomainNumber));\r
253 return ;\r
254 }\r
255 }\r
256 return ;\r
257}\r
258\r
259/**\r
260 Enable DMAR translation.\r
261\r
262 @retval EFI_SUCCESS DMAR translation is enabled.\r
263 @retval EFI_DEVICE_ERROR DMAR translation is not enabled.\r
264**/\r
265EFI_STATUS\r
266EnableDmar (\r
267 VOID\r
268 )\r
269{\r
270 UINTN Index;\r
271 UINT64 Reg64;\r
272 UINT32 Reg32;\r
273\r
274 AsmWbinvd();\r
275\r
276 for (Index = 0; Index < mVtdUnitNumber; Index++) {\r
277 DEBUG((DEBUG_INFO, ">>>>>>EnableDmar() for engine [%d] \n", Index));\r
278\r
279 if (mVtdUnitInformation[Index].ExtRootEntryTable != NULL) {\r
280 DEBUG((DEBUG_INFO, "ExtRootEntryTable 0x%x \n", mVtdUnitInformation[Index].ExtRootEntryTable));\r
281 MmioWrite64 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_RTADDR_REG, (UINT64)(UINTN)mVtdUnitInformation[Index].ExtRootEntryTable | BIT11);\r
282 } else {\r
283 DEBUG((DEBUG_INFO, "RootEntryTable 0x%x \n", mVtdUnitInformation[Index].RootEntryTable));\r
284 MmioWrite64 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_RTADDR_REG, (UINT64)(UINTN)mVtdUnitInformation[Index].RootEntryTable);\r
285 }\r
286\r
287 MmioWrite32 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_GCMD_REG, B_GMCD_REG_SRTP);\r
288\r
289 DEBUG((DEBUG_INFO, "EnableDmar: waiting for RTPS bit to be set... \n"));\r
290 do {\r
291 Reg32 = MmioRead32 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_GSTS_REG);\r
292 } while((Reg32 & B_GSTS_REG_RTPS) == 0);\r
293\r
294 //\r
295 // Init DMAr Fault Event and Data registers\r
296 //\r
297 Reg32 = MmioRead32 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_FEDATA_REG);\r
298\r
299 //\r
300 // Write Buffer Flush before invalidation\r
301 //\r
302 Reg32 = MmioRead32 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_CAP_REG);\r
303 if ((Reg32 & B_CAP_REG_RWBF) != 0) {\r
304 MmioWrite32 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_GCMD_REG, B_GMCD_REG_WBF);\r
305 }\r
306\r
307 //\r
308 // Invalidate the context cache\r
309 //\r
310 Reg64 = MmioRead64 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_CCMD_REG);\r
311 if ((Reg64 & B_CCMD_REG_ICC) != 0) {\r
312 DEBUG ((DEBUG_INFO,"ERROR: EnableDmar: B_CCMD_REG_ICC is set for VTD(%d)\n",Index));\r
313 return EFI_DEVICE_ERROR;\r
314 }\r
315\r
316 Reg64 &= ((~B_CCMD_REG_ICC) & (~B_CCMD_REG_CIRG_MASK));\r
317 Reg64 |= (B_CCMD_REG_ICC | V_CCMD_REG_CIRG_GLOBAL);\r
318 MmioWrite64 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_CCMD_REG, Reg64);\r
319\r
320 DEBUG((DEBUG_INFO, "EnableDmar: Waiting B_CCMD_REG_ICC ...\n"));\r
321 do {\r
322 Reg64 = MmioRead64 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_CCMD_REG);\r
323 } while ((Reg64 & B_CCMD_REG_ICC) != 0);\r
324\r
325 //\r
326 // Invalidate the IOTLB cache\r
327 //\r
328 DEBUG((DEBUG_INFO, "EnableDmar: IRO 0x%x\n", mVtdUnitInformation[Index].ECapReg.Bits.IRO));\r
329\r
330 Reg64 = MmioRead64 (mVtdUnitInformation[Index].VtdUnitBaseAddress + (mVtdUnitInformation[Index].ECapReg.Bits.IRO * 16) + R_IOTLB_REG);\r
331 if ((Reg64 & B_IOTLB_REG_IVT) != 0) {\r
332 DEBUG ((DEBUG_INFO,"ERROR: EnableDmar: B_IOTLB_REG_IVT is set for VTD(%d)\n", Index));\r
333 return EFI_DEVICE_ERROR;\r
334 }\r
335\r
336 Reg64 &= ((~B_IOTLB_REG_IVT) & (~B_IOTLB_REG_IIRG_MASK));\r
337 Reg64 |= (B_IOTLB_REG_IVT | V_IOTLB_REG_IIRG_GLOBAL);\r
338 MmioWrite64 (mVtdUnitInformation[Index].VtdUnitBaseAddress + (mVtdUnitInformation[Index].ECapReg.Bits.IRO * 16) + R_IOTLB_REG, Reg64);\r
339\r
340 DEBUG((DEBUG_INFO, "EnableDmar: Waiting B_IOTLB_REG_IVT ...\n"));\r
341 do {\r
342 Reg64 = MmioRead64 (mVtdUnitInformation[Index].VtdUnitBaseAddress + (mVtdUnitInformation[Index].ECapReg.Bits.IRO * 16) + R_IOTLB_REG);\r
343 } while ((Reg64 & B_IOTLB_REG_IVT) != 0);\r
344\r
345 //\r
346 // Enable VTd\r
347 //\r
348 MmioWrite32 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_GCMD_REG, B_GMCD_REG_TE);\r
349 DEBUG((DEBUG_INFO, "EnableDmar: Waiting B_GSTS_REG_TE ...\n"));\r
350 do {\r
351 Reg32 = MmioRead32 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_GSTS_REG);\r
352 } while ((Reg32 & B_GSTS_REG_TE) == 0);\r
353\r
354 DEBUG ((DEBUG_INFO,"VTD (%d) enabled!<<<<<<\n",Index));\r
355 }\r
356\r
357 mVtdEnabled = TRUE;\r
358\r
359 return EFI_SUCCESS;\r
360}\r
361\r
362/**\r
363 Disable DMAR translation.\r
364\r
365 @retval EFI_SUCCESS DMAR translation is disabled.\r
366 @retval EFI_DEVICE_ERROR DMAR translation is not disabled.\r
367**/\r
368EFI_STATUS\r
369DisableDmar (\r
370 VOID\r
371 )\r
372{\r
373 UINTN Index;\r
374 UINT32 Reg32;\r
375\r
376 AsmWbinvd();\r
377\r
378 for (Index = 0; Index < mVtdUnitNumber; Index++) {\r
379 DEBUG((DEBUG_INFO, ">>>>>>DisableDmar() for engine [%d] \n", Index));\r
380\r
381 //\r
382 // Write Buffer Flush before invalidation\r
383 //\r
384 Reg32 = MmioRead32 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_CAP_REG);\r
385 if ((Reg32 & B_CAP_REG_RWBF) != 0) {\r
386 MmioWrite32 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_GCMD_REG, B_GMCD_REG_WBF);\r
387 }\r
388\r
389 //\r
390 // Disable VTd\r
391 //\r
392 MmioWrite32 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_GCMD_REG, B_GMCD_REG_SRTP);\r
393 do {\r
394 Reg32 = MmioRead32 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_GSTS_REG);\r
395 } while((Reg32 & B_GSTS_REG_RTPS) == 0);\r
396\r
397 Reg32 = MmioRead32 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_GSTS_REG);\r
398 DEBUG((DEBUG_INFO, "DisableDmar: GSTS_REG - 0x%08x\n", Reg32));\r
399\r
400 DEBUG ((DEBUG_INFO,"VTD (%d) Disabled!<<<<<<\n",Index));\r
401 }\r
402\r
403 mVtdEnabled = FALSE;\r
404\r
405 return EFI_SUCCESS;\r
406}\r
407\r
408/**\r
409 Dump VTd capability registers.\r
410\r
411 @param[in] CapReg The capability register.\r
412**/\r
413VOID\r
414DumpVtdCapRegs (\r
415 IN VTD_CAP_REG *CapReg\r
416 )\r
417{\r
418 DEBUG((DEBUG_INFO, " CapReg:\n", CapReg->Uint64));\r
419 DEBUG((DEBUG_INFO, " ND - 0x%x\n", CapReg->Bits.ND));\r
420 DEBUG((DEBUG_INFO, " AFL - 0x%x\n", CapReg->Bits.AFL));\r
421 DEBUG((DEBUG_INFO, " RWBF - 0x%x\n", CapReg->Bits.RWBF));\r
422 DEBUG((DEBUG_INFO, " PLMR - 0x%x\n", CapReg->Bits.PLMR));\r
423 DEBUG((DEBUG_INFO, " PHMR - 0x%x\n", CapReg->Bits.PHMR));\r
424 DEBUG((DEBUG_INFO, " CM - 0x%x\n", CapReg->Bits.CM));\r
425 DEBUG((DEBUG_INFO, " SAGAW - 0x%x\n", CapReg->Bits.SAGAW));\r
426 DEBUG((DEBUG_INFO, " MGAW - 0x%x\n", CapReg->Bits.MGAW));\r
427 DEBUG((DEBUG_INFO, " ZLR - 0x%x\n", CapReg->Bits.ZLR));\r
428 DEBUG((DEBUG_INFO, " FRO - 0x%x\n", CapReg->Bits.FRO));\r
429 DEBUG((DEBUG_INFO, " SLLPS - 0x%x\n", CapReg->Bits.SLLPS));\r
430 DEBUG((DEBUG_INFO, " PSI - 0x%x\n", CapReg->Bits.PSI));\r
431 DEBUG((DEBUG_INFO, " NFR - 0x%x\n", CapReg->Bits.NFR));\r
432 DEBUG((DEBUG_INFO, " MAMV - 0x%x\n", CapReg->Bits.MAMV));\r
433 DEBUG((DEBUG_INFO, " DWD - 0x%x\n", CapReg->Bits.DWD));\r
434 DEBUG((DEBUG_INFO, " DRD - 0x%x\n", CapReg->Bits.DRD));\r
435 DEBUG((DEBUG_INFO, " FL1GP - 0x%x\n", CapReg->Bits.FL1GP));\r
436 DEBUG((DEBUG_INFO, " PI - 0x%x\n", CapReg->Bits.PI));\r
437}\r
438\r
439/**\r
440 Dump VTd extended capability registers.\r
441\r
442 @param[in] ECapReg The extended capability register.\r
443**/\r
444VOID\r
445DumpVtdECapRegs (\r
446 IN VTD_ECAP_REG *ECapReg\r
447 )\r
448{\r
449 DEBUG((DEBUG_INFO, " ECapReg:\n", ECapReg->Uint64));\r
450 DEBUG((DEBUG_INFO, " C - 0x%x\n", ECapReg->Bits.C));\r
451 DEBUG((DEBUG_INFO, " QI - 0x%x\n", ECapReg->Bits.QI));\r
452 DEBUG((DEBUG_INFO, " DT - 0x%x\n", ECapReg->Bits.DT));\r
453 DEBUG((DEBUG_INFO, " IR - 0x%x\n", ECapReg->Bits.IR));\r
454 DEBUG((DEBUG_INFO, " EIM - 0x%x\n", ECapReg->Bits.EIM));\r
455 DEBUG((DEBUG_INFO, " PT - 0x%x\n", ECapReg->Bits.PT));\r
456 DEBUG((DEBUG_INFO, " SC - 0x%x\n", ECapReg->Bits.SC));\r
457 DEBUG((DEBUG_INFO, " IRO - 0x%x\n", ECapReg->Bits.IRO));\r
458 DEBUG((DEBUG_INFO, " MHMV - 0x%x\n", ECapReg->Bits.MHMV));\r
459 DEBUG((DEBUG_INFO, " ECS - 0x%x\n", ECapReg->Bits.ECS));\r
460 DEBUG((DEBUG_INFO, " MTS - 0x%x\n", ECapReg->Bits.MTS));\r
461 DEBUG((DEBUG_INFO, " NEST - 0x%x\n", ECapReg->Bits.NEST));\r
462 DEBUG((DEBUG_INFO, " DIS - 0x%x\n", ECapReg->Bits.DIS));\r
463 DEBUG((DEBUG_INFO, " PASID - 0x%x\n", ECapReg->Bits.PASID));\r
464 DEBUG((DEBUG_INFO, " PRS - 0x%x\n", ECapReg->Bits.PRS));\r
465 DEBUG((DEBUG_INFO, " ERS - 0x%x\n", ECapReg->Bits.ERS));\r
466 DEBUG((DEBUG_INFO, " SRS - 0x%x\n", ECapReg->Bits.SRS));\r
467 DEBUG((DEBUG_INFO, " NWFS - 0x%x\n", ECapReg->Bits.NWFS));\r
468 DEBUG((DEBUG_INFO, " EAFS - 0x%x\n", ECapReg->Bits.EAFS));\r
469 DEBUG((DEBUG_INFO, " PSS - 0x%x\n", ECapReg->Bits.PSS));\r
470}\r
471\r
472/**\r
473 Dump VTd registers.\r
474\r
475 @param[in] VtdIndex The index of VTd engine.\r
476**/\r
477VOID\r
478DumpVtdRegs (\r
479 IN UINTN VtdIndex\r
480 )\r
481{\r
482 UINTN Index;\r
483 UINT64 Reg64;\r
484 VTD_FRCD_REG FrcdReg;\r
485 VTD_CAP_REG CapReg;\r
486 UINT32 Reg32;\r
487 VTD_SOURCE_ID SourceId;\r
488\r
489 DEBUG((DEBUG_INFO, "#### DumpVtdRegs(%d) Begin ####\n", VtdIndex));\r
490\r
491 Reg32 = MmioRead32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_VER_REG);\r
492 DEBUG((DEBUG_INFO, " VER_REG - 0x%08x\n", Reg32));\r
493\r
494 CapReg.Uint64 = MmioRead64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_CAP_REG);\r
495 DEBUG((DEBUG_INFO, " CAP_REG - 0x%016lx\n", CapReg.Uint64));\r
496\r
497 Reg64 = MmioRead64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_ECAP_REG);\r
498 DEBUG((DEBUG_INFO, " ECAP_REG - 0x%016lx\n", Reg64));\r
499\r
500 Reg32 = MmioRead32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_GSTS_REG);\r
501 DEBUG((DEBUG_INFO, " GSTS_REG - 0x%08x \n", Reg32));\r
502\r
503 Reg64 = MmioRead64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_RTADDR_REG);\r
504 DEBUG((DEBUG_INFO, " RTADDR_REG - 0x%016lx\n", Reg64));\r
505\r
506 Reg64 = MmioRead64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_CCMD_REG);\r
507 DEBUG((DEBUG_INFO, " CCMD_REG - 0x%016lx\n", Reg64));\r
508\r
509 Reg32 = MmioRead32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_FSTS_REG);\r
510 DEBUG((DEBUG_INFO, " FSTS_REG - 0x%08x\n", Reg32));\r
511\r
512 Reg32 = MmioRead32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_FECTL_REG);\r
513 DEBUG((DEBUG_INFO, " FECTL_REG - 0x%08x\n", Reg32));\r
514\r
515 Reg32 = MmioRead32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_FEDATA_REG);\r
516 DEBUG((DEBUG_INFO, " FEDATA_REG - 0x%08x\n", Reg32));\r
517\r
518 Reg32 = MmioRead32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_FEADDR_REG);\r
519 DEBUG((DEBUG_INFO, " FEADDR_REG - 0x%08x\n",Reg32));\r
520\r
521 Reg32 = MmioRead32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_FEUADDR_REG);\r
522 DEBUG((DEBUG_INFO, " FEUADDR_REG - 0x%08x\n",Reg32));\r
523\r
524 for (Index = 0; Index < (UINTN)CapReg.Bits.NFR + 1; Index++) {\r
525 FrcdReg.Uint64[0] = MmioRead64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + ((CapReg.Bits.FRO * 16) + (Index * 16) + R_FRCD_REG));\r
526 FrcdReg.Uint64[1] = MmioRead64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + ((CapReg.Bits.FRO * 16) + (Index * 16) + R_FRCD_REG + sizeof(UINT64)));\r
527 DEBUG((DEBUG_INFO, " FRCD_REG[%d] - 0x%016lx %016lx\n", Index, FrcdReg.Uint64[1], FrcdReg.Uint64[0]));\r
528 if (FrcdReg.Uint64[1] != 0 || FrcdReg.Uint64[0] != 0) {\r
76c6f69c 529 DEBUG((DEBUG_INFO, " Fault Info - 0x%016lx\n", VTD_64BITS_ADDRESS(FrcdReg.Bits.FILo, FrcdReg.Bits.FIHi)));\r
c049fc99
JY
530 SourceId.Uint16 = (UINT16)FrcdReg.Bits.SID;\r
531 DEBUG((DEBUG_INFO, " Source - B%02x D%02x F%02x\n", SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.Function));\r
532 DEBUG((DEBUG_INFO, " Type - %x (%a)\n", FrcdReg.Bits.T, FrcdReg.Bits.T ? "read" : "write"));\r
533 DEBUG((DEBUG_INFO, " Reason - %x\n", FrcdReg.Bits.FR));\r
534 }\r
535 }\r
536\r
537 Reg64 = MmioRead64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + (mVtdUnitInformation[VtdIndex].ECapReg.Bits.IRO * 16) + R_IVA_REG);\r
538 DEBUG((DEBUG_INFO, " IVA_REG - 0x%016lx\n",Reg64));\r
539\r
540 Reg64 = MmioRead64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + (mVtdUnitInformation[VtdIndex].ECapReg.Bits.IRO * 16) + R_IOTLB_REG);\r
541 DEBUG((DEBUG_INFO, " IOTLB_REG - 0x%016lx\n",Reg64));\r
542\r
543 DEBUG((DEBUG_INFO, "#### DumpVtdRegs(%d) End ####\n", VtdIndex));\r
544}\r
545\r
546/**\r
547 Dump VTd registers for all VTd engine.\r
548**/\r
549VOID\r
550DumpVtdRegsAll (\r
551 VOID\r
552 )\r
553{\r
554 UINTN Num;\r
555\r
556 for (Num = 0; Num < mVtdUnitNumber; Num++) {\r
557 DumpVtdRegs (Num);\r
558 }\r
559}\r
560\r
561/**\r
562 Dump VTd registers if there is error.\r
563**/\r
564VOID\r
565DumpVtdIfError (\r
566 VOID\r
567 )\r
568{\r
569 UINTN Num;\r
570 UINTN Index;\r
571 VTD_FRCD_REG FrcdReg;\r
572 VTD_CAP_REG CapReg;\r
573 UINT32 Reg32;\r
574 BOOLEAN HasError;\r
575\r
576 for (Num = 0; Num < mVtdUnitNumber; Num++) {\r
577 HasError = FALSE;\r
578 Reg32 = MmioRead32 (mVtdUnitInformation[Num].VtdUnitBaseAddress + R_FSTS_REG);\r
579 if (Reg32 != 0) {\r
580 HasError = TRUE;\r
581 }\r
582 Reg32 = MmioRead32 (mVtdUnitInformation[Num].VtdUnitBaseAddress + R_FECTL_REG);\r
583 if ((Reg32 & BIT30) != 0) {\r
584 HasError = TRUE;\r
585 }\r
586\r
587 CapReg.Uint64 = MmioRead64 (mVtdUnitInformation[Num].VtdUnitBaseAddress + R_CAP_REG);\r
588 for (Index = 0; Index < (UINTN)CapReg.Bits.NFR + 1; Index++) {\r
589 FrcdReg.Uint64[0] = MmioRead64 (mVtdUnitInformation[Num].VtdUnitBaseAddress + ((CapReg.Bits.FRO * 16) + (Index * 16) + R_FRCD_REG));\r
590 FrcdReg.Uint64[1] = MmioRead64 (mVtdUnitInformation[Num].VtdUnitBaseAddress + ((CapReg.Bits.FRO * 16) + (Index * 16) + R_FRCD_REG + sizeof(UINT64)));\r
591 if ((FrcdReg.Uint64[0] != 0) || (FrcdReg.Uint64[1] != 0)) {\r
592 HasError = TRUE;\r
593 }\r
594 }\r
595\r
596 if (HasError) {\r
597 DEBUG((DEBUG_INFO, "#### ERROR ####\n"));\r
598 DumpVtdRegs (Num);\r
599 DEBUG((DEBUG_INFO, "#### ERROR ####\n"));\r
600 }\r
601 }\r
602}\r