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