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