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