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