]> git.proxmox.com Git - mirror_edk2.git/blame - IntelSiliconPkg/Feature/VTd/IntelVTdDxe/VtdReg.c
IntelSiliconPkg/IntelVTdDxe: Move to feature dir.
[mirror_edk2.git] / IntelSiliconPkg / Feature / VTd / 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
f77d35c7
JY
190 if (mVtdUnitInformation[Index].PciDeviceInfo.PciDeviceDataNumber >= DomainNumber) {\r
191 DEBUG((DEBUG_ERROR, "!!!! Pci device Number(0x%x) >= DomainNumber(0x%x) !!!!\n", mVtdUnitInformation[Index].PciDeviceInfo.PciDeviceDataNumber, DomainNumber));\r
c049fc99
JY
192 return ;\r
193 }\r
194 }\r
195 return ;\r
196}\r
197\r
ffe77707
JY
198/**\r
199 Disable PMR in all VTd engine.\r
200**/\r
201VOID\r
202DisablePmr (\r
203 VOID\r
204 )\r
205{\r
206 UINT32 Reg32;\r
207 VTD_CAP_REG CapReg;\r
208 UINTN Index;\r
209\r
210 DEBUG ((DEBUG_INFO,"DisablePmr\n"));\r
211 for (Index = 0; Index < mVtdUnitNumber; Index++) {\r
212 CapReg.Uint64 = MmioRead64 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_CAP_REG);\r
213 if (CapReg.Bits.PLMR == 0 || CapReg.Bits.PHMR == 0) {\r
214 continue ;\r
215 }\r
216\r
217 Reg32 = MmioRead32 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_PMEN_ENABLE_REG);\r
218 if ((Reg32 & BIT0) != 0) {\r
219 MmioWrite32 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_PMEN_ENABLE_REG, 0x0);\r
220 do {\r
221 Reg32 = MmioRead32 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_PMEN_ENABLE_REG);\r
222 } while((Reg32 & BIT0) != 0);\r
223 DEBUG ((DEBUG_INFO,"Pmr(%d) disabled\n", Index));\r
224 } else {\r
225 DEBUG ((DEBUG_INFO,"Pmr(%d) not enabled\n", Index));\r
226 }\r
227 }\r
228 return ;\r
229}\r
230\r
c049fc99
JY
231/**\r
232 Enable DMAR translation.\r
233\r
234 @retval EFI_SUCCESS DMAR translation is enabled.\r
235 @retval EFI_DEVICE_ERROR DMAR translation is not enabled.\r
236**/\r
237EFI_STATUS\r
238EnableDmar (\r
239 VOID\r
240 )\r
241{\r
242 UINTN Index;\r
c049fc99
JY
243 UINT32 Reg32;\r
244\r
c049fc99
JY
245 for (Index = 0; Index < mVtdUnitNumber; Index++) {\r
246 DEBUG((DEBUG_INFO, ">>>>>>EnableDmar() for engine [%d] \n", Index));\r
247\r
248 if (mVtdUnitInformation[Index].ExtRootEntryTable != NULL) {\r
249 DEBUG((DEBUG_INFO, "ExtRootEntryTable 0x%x \n", mVtdUnitInformation[Index].ExtRootEntryTable));\r
250 MmioWrite64 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_RTADDR_REG, (UINT64)(UINTN)mVtdUnitInformation[Index].ExtRootEntryTable | BIT11);\r
251 } else {\r
252 DEBUG((DEBUG_INFO, "RootEntryTable 0x%x \n", mVtdUnitInformation[Index].RootEntryTable));\r
253 MmioWrite64 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_RTADDR_REG, (UINT64)(UINTN)mVtdUnitInformation[Index].RootEntryTable);\r
254 }\r
255\r
256 MmioWrite32 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_GCMD_REG, B_GMCD_REG_SRTP);\r
257\r
258 DEBUG((DEBUG_INFO, "EnableDmar: waiting for RTPS bit to be set... \n"));\r
259 do {\r
260 Reg32 = MmioRead32 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_GSTS_REG);\r
261 } while((Reg32 & B_GSTS_REG_RTPS) == 0);\r
262\r
263 //\r
264 // Init DMAr Fault Event and Data registers\r
265 //\r
266 Reg32 = MmioRead32 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_FEDATA_REG);\r
267\r
268 //\r
269 // Write Buffer Flush before invalidation\r
270 //\r
4ad5f597 271 FlushWriteBuffer (Index);\r
c049fc99
JY
272\r
273 //\r
274 // Invalidate the context cache\r
275 //\r
4ad5f597 276 InvalidateContextCache (Index);\r
c049fc99
JY
277\r
278 //\r
279 // Invalidate the IOTLB cache\r
280 //\r
4ad5f597 281 InvalidateIOTLB (Index);\r
c049fc99
JY
282\r
283 //\r
284 // Enable VTd\r
285 //\r
286 MmioWrite32 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_GCMD_REG, B_GMCD_REG_TE);\r
287 DEBUG((DEBUG_INFO, "EnableDmar: Waiting B_GSTS_REG_TE ...\n"));\r
288 do {\r
289 Reg32 = MmioRead32 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_GSTS_REG);\r
290 } while ((Reg32 & B_GSTS_REG_TE) == 0);\r
291\r
292 DEBUG ((DEBUG_INFO,"VTD (%d) enabled!<<<<<<\n",Index));\r
293 }\r
294\r
ffe77707
JY
295 //\r
296 // Need disable PMR, since we already setup translation table.\r
297 //\r
298 DisablePmr ();\r
299\r
c049fc99
JY
300 mVtdEnabled = TRUE;\r
301\r
302 return EFI_SUCCESS;\r
303}\r
304\r
305/**\r
306 Disable DMAR translation.\r
307\r
308 @retval EFI_SUCCESS DMAR translation is disabled.\r
309 @retval EFI_DEVICE_ERROR DMAR translation is not disabled.\r
310**/\r
311EFI_STATUS\r
312DisableDmar (\r
313 VOID\r
314 )\r
315{\r
316 UINTN Index;\r
4ad5f597 317 UINTN SubIndex;\r
c049fc99
JY
318 UINT32 Reg32;\r
319\r
c049fc99
JY
320 for (Index = 0; Index < mVtdUnitNumber; Index++) {\r
321 DEBUG((DEBUG_INFO, ">>>>>>DisableDmar() for engine [%d] \n", Index));\r
322\r
323 //\r
324 // Write Buffer Flush before invalidation\r
325 //\r
4ad5f597 326 FlushWriteBuffer (Index);\r
c049fc99
JY
327\r
328 //\r
329 // Disable VTd\r
330 //\r
331 MmioWrite32 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_GCMD_REG, B_GMCD_REG_SRTP);\r
332 do {\r
333 Reg32 = MmioRead32 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_GSTS_REG);\r
334 } while((Reg32 & B_GSTS_REG_RTPS) == 0);\r
335\r
336 Reg32 = MmioRead32 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_GSTS_REG);\r
337 DEBUG((DEBUG_INFO, "DisableDmar: GSTS_REG - 0x%08x\n", Reg32));\r
338\r
339 DEBUG ((DEBUG_INFO,"VTD (%d) Disabled!<<<<<<\n",Index));\r
340 }\r
341\r
342 mVtdEnabled = FALSE;\r
343\r
4ad5f597
JY
344 for (Index = 0; Index < mVtdUnitNumber; Index++) {\r
345 DEBUG((DEBUG_INFO, "engine [%d] access\n", Index));\r
f77d35c7 346 for (SubIndex = 0; SubIndex < mVtdUnitInformation[Index].PciDeviceInfo.PciDeviceDataNumber; SubIndex++) {\r
4ad5f597
JY
347 DEBUG ((DEBUG_INFO, " PCI S%04X B%02x D%02x F%02x - %d\n",\r
348 mVtdUnitInformation[Index].Segment,\r
f77d35c7
JY
349 mVtdUnitInformation[Index].PciDeviceInfo.PciDeviceData[Index].PciSourceId.Bits.Bus,\r
350 mVtdUnitInformation[Index].PciDeviceInfo.PciDeviceData[Index].PciSourceId.Bits.Device,\r
351 mVtdUnitInformation[Index].PciDeviceInfo.PciDeviceData[Index].PciSourceId.Bits.Function,\r
352 mVtdUnitInformation[Index].PciDeviceInfo.PciDeviceData[Index].AccessCount\r
4ad5f597
JY
353 ));\r
354 }\r
355 }\r
356\r
c049fc99
JY
357 return EFI_SUCCESS;\r
358}\r
359\r
360/**\r
361 Dump VTd capability registers.\r
362\r
363 @param[in] CapReg The capability register.\r
364**/\r
365VOID\r
366DumpVtdCapRegs (\r
367 IN VTD_CAP_REG *CapReg\r
368 )\r
369{\r
370 DEBUG((DEBUG_INFO, " CapReg:\n", CapReg->Uint64));\r
371 DEBUG((DEBUG_INFO, " ND - 0x%x\n", CapReg->Bits.ND));\r
372 DEBUG((DEBUG_INFO, " AFL - 0x%x\n", CapReg->Bits.AFL));\r
373 DEBUG((DEBUG_INFO, " RWBF - 0x%x\n", CapReg->Bits.RWBF));\r
374 DEBUG((DEBUG_INFO, " PLMR - 0x%x\n", CapReg->Bits.PLMR));\r
375 DEBUG((DEBUG_INFO, " PHMR - 0x%x\n", CapReg->Bits.PHMR));\r
376 DEBUG((DEBUG_INFO, " CM - 0x%x\n", CapReg->Bits.CM));\r
377 DEBUG((DEBUG_INFO, " SAGAW - 0x%x\n", CapReg->Bits.SAGAW));\r
378 DEBUG((DEBUG_INFO, " MGAW - 0x%x\n", CapReg->Bits.MGAW));\r
379 DEBUG((DEBUG_INFO, " ZLR - 0x%x\n", CapReg->Bits.ZLR));\r
380 DEBUG((DEBUG_INFO, " FRO - 0x%x\n", CapReg->Bits.FRO));\r
381 DEBUG((DEBUG_INFO, " SLLPS - 0x%x\n", CapReg->Bits.SLLPS));\r
382 DEBUG((DEBUG_INFO, " PSI - 0x%x\n", CapReg->Bits.PSI));\r
383 DEBUG((DEBUG_INFO, " NFR - 0x%x\n", CapReg->Bits.NFR));\r
384 DEBUG((DEBUG_INFO, " MAMV - 0x%x\n", CapReg->Bits.MAMV));\r
385 DEBUG((DEBUG_INFO, " DWD - 0x%x\n", CapReg->Bits.DWD));\r
386 DEBUG((DEBUG_INFO, " DRD - 0x%x\n", CapReg->Bits.DRD));\r
387 DEBUG((DEBUG_INFO, " FL1GP - 0x%x\n", CapReg->Bits.FL1GP));\r
388 DEBUG((DEBUG_INFO, " PI - 0x%x\n", CapReg->Bits.PI));\r
389}\r
390\r
391/**\r
392 Dump VTd extended capability registers.\r
393\r
394 @param[in] ECapReg The extended capability register.\r
395**/\r
396VOID\r
397DumpVtdECapRegs (\r
398 IN VTD_ECAP_REG *ECapReg\r
399 )\r
400{\r
401 DEBUG((DEBUG_INFO, " ECapReg:\n", ECapReg->Uint64));\r
402 DEBUG((DEBUG_INFO, " C - 0x%x\n", ECapReg->Bits.C));\r
403 DEBUG((DEBUG_INFO, " QI - 0x%x\n", ECapReg->Bits.QI));\r
404 DEBUG((DEBUG_INFO, " DT - 0x%x\n", ECapReg->Bits.DT));\r
405 DEBUG((DEBUG_INFO, " IR - 0x%x\n", ECapReg->Bits.IR));\r
406 DEBUG((DEBUG_INFO, " EIM - 0x%x\n", ECapReg->Bits.EIM));\r
407 DEBUG((DEBUG_INFO, " PT - 0x%x\n", ECapReg->Bits.PT));\r
408 DEBUG((DEBUG_INFO, " SC - 0x%x\n", ECapReg->Bits.SC));\r
409 DEBUG((DEBUG_INFO, " IRO - 0x%x\n", ECapReg->Bits.IRO));\r
410 DEBUG((DEBUG_INFO, " MHMV - 0x%x\n", ECapReg->Bits.MHMV));\r
411 DEBUG((DEBUG_INFO, " ECS - 0x%x\n", ECapReg->Bits.ECS));\r
412 DEBUG((DEBUG_INFO, " MTS - 0x%x\n", ECapReg->Bits.MTS));\r
413 DEBUG((DEBUG_INFO, " NEST - 0x%x\n", ECapReg->Bits.NEST));\r
414 DEBUG((DEBUG_INFO, " DIS - 0x%x\n", ECapReg->Bits.DIS));\r
415 DEBUG((DEBUG_INFO, " PASID - 0x%x\n", ECapReg->Bits.PASID));\r
416 DEBUG((DEBUG_INFO, " PRS - 0x%x\n", ECapReg->Bits.PRS));\r
417 DEBUG((DEBUG_INFO, " ERS - 0x%x\n", ECapReg->Bits.ERS));\r
418 DEBUG((DEBUG_INFO, " SRS - 0x%x\n", ECapReg->Bits.SRS));\r
419 DEBUG((DEBUG_INFO, " NWFS - 0x%x\n", ECapReg->Bits.NWFS));\r
420 DEBUG((DEBUG_INFO, " EAFS - 0x%x\n", ECapReg->Bits.EAFS));\r
421 DEBUG((DEBUG_INFO, " PSS - 0x%x\n", ECapReg->Bits.PSS));\r
422}\r
423\r
424/**\r
425 Dump VTd registers.\r
426\r
427 @param[in] VtdIndex The index of VTd engine.\r
428**/\r
429VOID\r
430DumpVtdRegs (\r
431 IN UINTN VtdIndex\r
432 )\r
433{\r
434 UINTN Index;\r
435 UINT64 Reg64;\r
436 VTD_FRCD_REG FrcdReg;\r
437 VTD_CAP_REG CapReg;\r
438 UINT32 Reg32;\r
439 VTD_SOURCE_ID SourceId;\r
440\r
441 DEBUG((DEBUG_INFO, "#### DumpVtdRegs(%d) Begin ####\n", VtdIndex));\r
442\r
443 Reg32 = MmioRead32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_VER_REG);\r
444 DEBUG((DEBUG_INFO, " VER_REG - 0x%08x\n", Reg32));\r
445\r
446 CapReg.Uint64 = MmioRead64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_CAP_REG);\r
447 DEBUG((DEBUG_INFO, " CAP_REG - 0x%016lx\n", CapReg.Uint64));\r
448\r
449 Reg64 = MmioRead64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_ECAP_REG);\r
450 DEBUG((DEBUG_INFO, " ECAP_REG - 0x%016lx\n", Reg64));\r
451\r
452 Reg32 = MmioRead32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_GSTS_REG);\r
453 DEBUG((DEBUG_INFO, " GSTS_REG - 0x%08x \n", Reg32));\r
454\r
455 Reg64 = MmioRead64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_RTADDR_REG);\r
456 DEBUG((DEBUG_INFO, " RTADDR_REG - 0x%016lx\n", Reg64));\r
457\r
458 Reg64 = MmioRead64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_CCMD_REG);\r
459 DEBUG((DEBUG_INFO, " CCMD_REG - 0x%016lx\n", Reg64));\r
460\r
461 Reg32 = MmioRead32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_FSTS_REG);\r
462 DEBUG((DEBUG_INFO, " FSTS_REG - 0x%08x\n", Reg32));\r
463\r
464 Reg32 = MmioRead32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_FECTL_REG);\r
465 DEBUG((DEBUG_INFO, " FECTL_REG - 0x%08x\n", Reg32));\r
466\r
467 Reg32 = MmioRead32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_FEDATA_REG);\r
468 DEBUG((DEBUG_INFO, " FEDATA_REG - 0x%08x\n", Reg32));\r
469\r
470 Reg32 = MmioRead32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_FEADDR_REG);\r
471 DEBUG((DEBUG_INFO, " FEADDR_REG - 0x%08x\n",Reg32));\r
472\r
473 Reg32 = MmioRead32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_FEUADDR_REG);\r
474 DEBUG((DEBUG_INFO, " FEUADDR_REG - 0x%08x\n",Reg32));\r
475\r
476 for (Index = 0; Index < (UINTN)CapReg.Bits.NFR + 1; Index++) {\r
477 FrcdReg.Uint64[0] = MmioRead64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + ((CapReg.Bits.FRO * 16) + (Index * 16) + R_FRCD_REG));\r
478 FrcdReg.Uint64[1] = MmioRead64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + ((CapReg.Bits.FRO * 16) + (Index * 16) + R_FRCD_REG + sizeof(UINT64)));\r
479 DEBUG((DEBUG_INFO, " FRCD_REG[%d] - 0x%016lx %016lx\n", Index, FrcdReg.Uint64[1], FrcdReg.Uint64[0]));\r
480 if (FrcdReg.Uint64[1] != 0 || FrcdReg.Uint64[0] != 0) {\r
76c6f69c 481 DEBUG((DEBUG_INFO, " Fault Info - 0x%016lx\n", VTD_64BITS_ADDRESS(FrcdReg.Bits.FILo, FrcdReg.Bits.FIHi)));\r
c049fc99
JY
482 SourceId.Uint16 = (UINT16)FrcdReg.Bits.SID;\r
483 DEBUG((DEBUG_INFO, " Source - B%02x D%02x F%02x\n", SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.Function));\r
484 DEBUG((DEBUG_INFO, " Type - %x (%a)\n", FrcdReg.Bits.T, FrcdReg.Bits.T ? "read" : "write"));\r
485 DEBUG((DEBUG_INFO, " Reason - %x\n", FrcdReg.Bits.FR));\r
486 }\r
487 }\r
488\r
489 Reg64 = MmioRead64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + (mVtdUnitInformation[VtdIndex].ECapReg.Bits.IRO * 16) + R_IVA_REG);\r
490 DEBUG((DEBUG_INFO, " IVA_REG - 0x%016lx\n",Reg64));\r
491\r
492 Reg64 = MmioRead64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + (mVtdUnitInformation[VtdIndex].ECapReg.Bits.IRO * 16) + R_IOTLB_REG);\r
493 DEBUG((DEBUG_INFO, " IOTLB_REG - 0x%016lx\n",Reg64));\r
494\r
495 DEBUG((DEBUG_INFO, "#### DumpVtdRegs(%d) End ####\n", VtdIndex));\r
496}\r
497\r
498/**\r
499 Dump VTd registers for all VTd engine.\r
500**/\r
501VOID\r
502DumpVtdRegsAll (\r
503 VOID\r
504 )\r
505{\r
506 UINTN Num;\r
507\r
508 for (Num = 0; Num < mVtdUnitNumber; Num++) {\r
509 DumpVtdRegs (Num);\r
510 }\r
511}\r
512\r
513/**\r
514 Dump VTd registers if there is error.\r
515**/\r
516VOID\r
517DumpVtdIfError (\r
518 VOID\r
519 )\r
520{\r
521 UINTN Num;\r
522 UINTN Index;\r
523 VTD_FRCD_REG FrcdReg;\r
524 VTD_CAP_REG CapReg;\r
525 UINT32 Reg32;\r
526 BOOLEAN HasError;\r
527\r
528 for (Num = 0; Num < mVtdUnitNumber; Num++) {\r
529 HasError = FALSE;\r
530 Reg32 = MmioRead32 (mVtdUnitInformation[Num].VtdUnitBaseAddress + R_FSTS_REG);\r
531 if (Reg32 != 0) {\r
532 HasError = TRUE;\r
533 }\r
534 Reg32 = MmioRead32 (mVtdUnitInformation[Num].VtdUnitBaseAddress + R_FECTL_REG);\r
535 if ((Reg32 & BIT30) != 0) {\r
536 HasError = TRUE;\r
537 }\r
538\r
539 CapReg.Uint64 = MmioRead64 (mVtdUnitInformation[Num].VtdUnitBaseAddress + R_CAP_REG);\r
540 for (Index = 0; Index < (UINTN)CapReg.Bits.NFR + 1; Index++) {\r
541 FrcdReg.Uint64[0] = MmioRead64 (mVtdUnitInformation[Num].VtdUnitBaseAddress + ((CapReg.Bits.FRO * 16) + (Index * 16) + R_FRCD_REG));\r
542 FrcdReg.Uint64[1] = MmioRead64 (mVtdUnitInformation[Num].VtdUnitBaseAddress + ((CapReg.Bits.FRO * 16) + (Index * 16) + R_FRCD_REG + sizeof(UINT64)));\r
ffe77707 543 if (FrcdReg.Bits.F != 0) {\r
c049fc99
JY
544 HasError = TRUE;\r
545 }\r
546 }\r
547\r
548 if (HasError) {\r
4d150848 549 DEBUG((DEBUG_INFO, "\n#### ERROR ####\n"));\r
c049fc99 550 DumpVtdRegs (Num);\r
4d150848 551 DEBUG((DEBUG_INFO, "#### ERROR ####\n\n"));\r
ffe77707
JY
552 //\r
553 // Clear\r
554 //\r
555 for (Index = 0; Index < (UINTN)CapReg.Bits.NFR + 1; Index++) {\r
556 FrcdReg.Uint64[1] = MmioRead64 (mVtdUnitInformation[Num].VtdUnitBaseAddress + ((CapReg.Bits.FRO * 16) + (Index * 16) + R_FRCD_REG + sizeof(UINT64)));\r
557 if (FrcdReg.Bits.F != 0) {\r
558 FrcdReg.Bits.F = 0;\r
559 MmioWrite64 (mVtdUnitInformation[Num].VtdUnitBaseAddress + ((CapReg.Bits.FRO * 16) + (Index * 16) + R_FRCD_REG + sizeof(UINT64)), FrcdReg.Uint64[1]);\r
560 }\r
561 MmioWrite32 (mVtdUnitInformation[Num].VtdUnitBaseAddress + R_FSTS_REG, MmioRead32 (mVtdUnitInformation[Num].VtdUnitBaseAddress + R_FSTS_REG));\r
562 }\r
c049fc99
JY
563 }\r
564 }\r
565}\r