]>
git.proxmox.com Git - mirror_edk2.git/blob - IntelSiliconPkg/Feature/VTd/IntelVTdDxe/VtdReg.c
3 Copyright (c) 2017 - 2018, Intel Corporation. All rights reserved.<BR>
4 SPDX-License-Identifier: BSD-2-Clause-Patent
8 #include "DmaProtection.h"
11 VTD_UNIT_INFORMATION
*mVtdUnitInformation
;
16 Flush VTD page table and context table memory.
18 This action is to make sure the IOMMU engine can get final data in memory.
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.
25 FlushPageTableMemory (
31 if (mVtdUnitInformation
[VtdIndex
].ECapReg
.Bits
.C
== 0) {
32 WriteBackDataCacheRange ((VOID
*)Base
, Size
);
37 Flush VTd engine write buffer.
39 @param[in] VtdIndex The index used to identify a VTd engine.
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
);
52 Reg32
= MmioRead32 (mVtdUnitInformation
[VtdIndex
].VtdUnitBaseAddress
+ R_GSTS_REG
);
53 } while ((Reg32
& B_GSTS_REG_WBF
) != 0);
58 Invalidate VTd context cache.
60 @param[in] VtdIndex The index used to identify a VTd engine.
63 InvalidateContextCache (
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
;
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
);
80 Reg64
= MmioRead64 (mVtdUnitInformation
[VtdIndex
].VtdUnitBaseAddress
+ R_CCMD_REG
);
81 } while ((Reg64
& B_CCMD_REG_ICC
) != 0);
89 @param[in] VtdIndex The index used to identify a VTd engine.
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
;
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
);
109 Reg64
= MmioRead64 (mVtdUnitInformation
[VtdIndex
].VtdUnitBaseAddress
+ (mVtdUnitInformation
[VtdIndex
].ECapReg
.Bits
.IRO
* 16) + R_IOTLB_REG
);
110 } while ((Reg64
& B_IOTLB_REG_IVT
) != 0);
116 Invalid VTd global IOTLB.
118 @param[in] VtdIndex The index of VTd engine.
120 @retval EFI_SUCCESS VTd global IOTLB is invalidated.
121 @retval EFI_DEVICE_ERROR VTd global IOTLB is not invalidated.
124 InvalidateVtdIOTLBGlobal (
132 DEBUG((DEBUG_VERBOSE
, "InvalidateVtdIOTLBGlobal(%d)\n", VtdIndex
));
135 // Write Buffer Flush before invalidation
137 FlushWriteBuffer (VtdIndex
);
140 // Invalidate the context cache
142 if (mVtdUnitInformation
[VtdIndex
].HasDirtyContext
) {
143 InvalidateContextCache (VtdIndex
);
147 // Invalidate the IOTLB cache
149 if (mVtdUnitInformation
[VtdIndex
].HasDirtyContext
|| mVtdUnitInformation
[VtdIndex
].HasDirtyPages
) {
150 InvalidateIOTLB (VtdIndex
);
157 Prepare VTD configuration.
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
);
174 if ((mVtdUnitInformation
[Index
].CapReg
.Bits
.SLLPS
& BIT0
) == 0) {
175 DEBUG((DEBUG_WARN
, "!!!! 2MB super page is not supported on VTD %d !!!!\n", Index
));
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
));
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
));
192 Disable PMR in all VTd engine.
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) {
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);
214 Reg32
= MmioRead32 (mVtdUnitInformation
[Index
].VtdUnitBaseAddress
+ R_PMEN_ENABLE_REG
);
215 } while((Reg32
& BIT0
) != 0);
216 DEBUG ((DEBUG_INFO
,"Pmr(%d) disabled\n", Index
));
218 DEBUG ((DEBUG_INFO
,"Pmr(%d) not enabled\n", Index
));
225 Enable DMAR translation.
227 @retval EFI_SUCCESS DMAR translation is enabled.
228 @retval EFI_DEVICE_ERROR DMAR translation is not enabled.
238 for (Index
= 0; Index
< mVtdUnitNumber
; Index
++) {
239 DEBUG((DEBUG_INFO
, ">>>>>>EnableDmar() for engine [%d] \n", Index
));
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
);
245 DEBUG((DEBUG_INFO
, "RootEntryTable 0x%x \n", mVtdUnitInformation
[Index
].RootEntryTable
));
246 MmioWrite64 (mVtdUnitInformation
[Index
].VtdUnitBaseAddress
+ R_RTADDR_REG
, (UINT64
)(UINTN
)mVtdUnitInformation
[Index
].RootEntryTable
);
249 MmioWrite32 (mVtdUnitInformation
[Index
].VtdUnitBaseAddress
+ R_GCMD_REG
, B_GMCD_REG_SRTP
);
251 DEBUG((DEBUG_INFO
, "EnableDmar: waiting for RTPS bit to be set... \n"));
253 Reg32
= MmioRead32 (mVtdUnitInformation
[Index
].VtdUnitBaseAddress
+ R_GSTS_REG
);
254 } while((Reg32
& B_GSTS_REG_RTPS
) == 0);
257 // Init DMAr Fault Event and Data registers
259 Reg32
= MmioRead32 (mVtdUnitInformation
[Index
].VtdUnitBaseAddress
+ R_FEDATA_REG
);
262 // Write Buffer Flush before invalidation
264 FlushWriteBuffer (Index
);
267 // Invalidate the context cache
269 InvalidateContextCache (Index
);
272 // Invalidate the IOTLB cache
274 InvalidateIOTLB (Index
);
279 MmioWrite32 (mVtdUnitInformation
[Index
].VtdUnitBaseAddress
+ R_GCMD_REG
, B_GMCD_REG_TE
);
280 DEBUG((DEBUG_INFO
, "EnableDmar: Waiting B_GSTS_REG_TE ...\n"));
282 Reg32
= MmioRead32 (mVtdUnitInformation
[Index
].VtdUnitBaseAddress
+ R_GSTS_REG
);
283 } while ((Reg32
& B_GSTS_REG_TE
) == 0);
285 DEBUG ((DEBUG_INFO
,"VTD (%d) enabled!<<<<<<\n",Index
));
289 // Need disable PMR, since we already setup translation table.
299 Disable DMAR translation.
301 @retval EFI_SUCCESS DMAR translation is disabled.
302 @retval EFI_DEVICE_ERROR DMAR translation is not disabled.
313 for (Index
= 0; Index
< mVtdUnitNumber
; Index
++) {
314 DEBUG((DEBUG_INFO
, ">>>>>>DisableDmar() for engine [%d] \n", Index
));
317 // Write Buffer Flush before invalidation
319 FlushWriteBuffer (Index
);
324 MmioWrite32 (mVtdUnitInformation
[Index
].VtdUnitBaseAddress
+ R_GCMD_REG
, B_GMCD_REG_SRTP
);
326 Reg32
= MmioRead32 (mVtdUnitInformation
[Index
].VtdUnitBaseAddress
+ R_GSTS_REG
);
327 } while((Reg32
& B_GSTS_REG_RTPS
) == 0);
329 Reg32
= MmioRead32 (mVtdUnitInformation
[Index
].VtdUnitBaseAddress
+ R_GSTS_REG
);
330 DEBUG((DEBUG_INFO
, "DisableDmar: GSTS_REG - 0x%08x\n", Reg32
));
332 DEBUG ((DEBUG_INFO
,"VTD (%d) Disabled!<<<<<<\n",Index
));
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
354 Dump VTd capability registers.
356 @param[in] CapReg The capability register.
360 IN VTD_CAP_REG
*CapReg
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
));
385 Dump VTd extended capability registers.
387 @param[in] ECapReg The extended capability register.
391 IN VTD_ECAP_REG
*ECapReg
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
));
420 @param[in] VtdIndex The index of VTd engine.
429 VTD_FRCD_REG FrcdReg
;
432 VTD_SOURCE_ID SourceId
;
434 DEBUG((DEBUG_INFO
, "#### DumpVtdRegs(%d) Begin ####\n", VtdIndex
));
436 Reg32
= MmioRead32 (mVtdUnitInformation
[VtdIndex
].VtdUnitBaseAddress
+ R_VER_REG
);
437 DEBUG((DEBUG_INFO
, " VER_REG - 0x%08x\n", Reg32
));
439 CapReg
.Uint64
= MmioRead64 (mVtdUnitInformation
[VtdIndex
].VtdUnitBaseAddress
+ R_CAP_REG
);
440 DEBUG((DEBUG_INFO
, " CAP_REG - 0x%016lx\n", CapReg
.Uint64
));
442 Reg64
= MmioRead64 (mVtdUnitInformation
[VtdIndex
].VtdUnitBaseAddress
+ R_ECAP_REG
);
443 DEBUG((DEBUG_INFO
, " ECAP_REG - 0x%016lx\n", Reg64
));
445 Reg32
= MmioRead32 (mVtdUnitInformation
[VtdIndex
].VtdUnitBaseAddress
+ R_GSTS_REG
);
446 DEBUG((DEBUG_INFO
, " GSTS_REG - 0x%08x \n", Reg32
));
448 Reg64
= MmioRead64 (mVtdUnitInformation
[VtdIndex
].VtdUnitBaseAddress
+ R_RTADDR_REG
);
449 DEBUG((DEBUG_INFO
, " RTADDR_REG - 0x%016lx\n", Reg64
));
451 Reg64
= MmioRead64 (mVtdUnitInformation
[VtdIndex
].VtdUnitBaseAddress
+ R_CCMD_REG
);
452 DEBUG((DEBUG_INFO
, " CCMD_REG - 0x%016lx\n", Reg64
));
454 Reg32
= MmioRead32 (mVtdUnitInformation
[VtdIndex
].VtdUnitBaseAddress
+ R_FSTS_REG
);
455 DEBUG((DEBUG_INFO
, " FSTS_REG - 0x%08x\n", Reg32
));
457 Reg32
= MmioRead32 (mVtdUnitInformation
[VtdIndex
].VtdUnitBaseAddress
+ R_FECTL_REG
);
458 DEBUG((DEBUG_INFO
, " FECTL_REG - 0x%08x\n", Reg32
));
460 Reg32
= MmioRead32 (mVtdUnitInformation
[VtdIndex
].VtdUnitBaseAddress
+ R_FEDATA_REG
);
461 DEBUG((DEBUG_INFO
, " FEDATA_REG - 0x%08x\n", Reg32
));
463 Reg32
= MmioRead32 (mVtdUnitInformation
[VtdIndex
].VtdUnitBaseAddress
+ R_FEADDR_REG
);
464 DEBUG((DEBUG_INFO
, " FEADDR_REG - 0x%08x\n",Reg32
));
466 Reg32
= MmioRead32 (mVtdUnitInformation
[VtdIndex
].VtdUnitBaseAddress
+ R_FEUADDR_REG
);
467 DEBUG((DEBUG_INFO
, " FEUADDR_REG - 0x%08x\n",Reg32
));
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
));
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
));
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
));
488 DEBUG((DEBUG_INFO
, "#### DumpVtdRegs(%d) End ####\n", VtdIndex
));
492 Dump VTd registers for all VTd engine.
501 for (Num
= 0; Num
< mVtdUnitNumber
; Num
++) {
507 Dump VTd registers if there is error.
516 VTD_FRCD_REG FrcdReg
;
521 for (Num
= 0; Num
< mVtdUnitNumber
; Num
++) {
523 Reg32
= MmioRead32 (mVtdUnitInformation
[Num
].VtdUnitBaseAddress
+ R_FSTS_REG
);
527 Reg32
= MmioRead32 (mVtdUnitInformation
[Num
].VtdUnitBaseAddress
+ R_FECTL_REG
);
528 if ((Reg32
& BIT30
) != 0) {
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) {
542 REPORT_STATUS_CODE (EFI_ERROR_CODE
, PcdGet32 (PcdErrorCodeVTdError
));
543 DEBUG((DEBUG_INFO
, "\n#### ERROR ####\n"));
545 DEBUG((DEBUG_INFO
, "#### ERROR ####\n\n"));
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) {
553 // Software writes the value read from this field (F) to Clear it.
555 MmioWrite64 (mVtdUnitInformation
[Num
].VtdUnitBaseAddress
+ ((CapReg
.Bits
.FRO
* 16) + (Index
* 16) + R_FRCD_REG
+ sizeof(UINT64
)), FrcdReg
.Uint64
[1]);
558 MmioWrite32 (mVtdUnitInformation
[Num
].VtdUnitBaseAddress
+ R_FSTS_REG
, MmioRead32 (mVtdUnitInformation
[Num
].VtdUnitBaseAddress
+ R_FSTS_REG
));