* [PATCH] IntelSiliconPkg/VTd: Use 256-bit invaildation queue descriptor
@ 2022-11-21 5:43 Sheng Wei
0 siblings, 0 replies; 2+ messages in thread
From: Sheng Wei @ 2022-11-21 5:43 UTC (permalink / raw)
To: devel; +Cc: Ray Ni, Rangasai V Chaganty, Jenny Huang, Robert Kowalewski
256-bit invaildation queue descriptor could be used for both
abort DMA mode and legacy mode.
Change-Id: Ib3b94d6c5782d42c53056204312f6f4ad513344e
Signed-off-by: Sheng Wei <w.sheng@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
Cc: Rangasai V Chaganty <rangasai.v.chaganty@intel.com>
Cc: Jenny Huang <jenny.huang@intel.com>
Cc: Robert Kowalewski <robert.kowalewski@intel.com>
---
.../VTd/IntelVTdDmarPei/IntelVTdDmar.c | 172 ++++++++-----
.../VTd/IntelVTdDmarPei/IntelVTdDmarPei.h | 5 +-
.../Feature/VTd/IntelVTdDxe/DmaProtection.c | 3 +
.../Feature/VTd/IntelVTdDxe/DmaProtection.h | 5 +-
.../Feature/VTd/IntelVTdDxe/VtdReg.c | 232 +++++++++++-------
.../Include/IndustryStandard/Vtd.h | 65 ++++-
6 files changed, 329 insertions(+), 153 deletions(-)
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.c
index af85a3d8e..87d5edaa6 100644
--- a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.c
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.c
@@ -79,10 +79,11 @@ PerpareCacheInvalidationInterface (
IN VTD_UNIT_INFO *VTdUnitInfo
)
{
- UINT16 QueueSize;
- UINT64 Reg64;
+ UINT8 DescriptorWidth;
+ UINTN QueueSize;
UINT32 Reg32;
VTD_ECAP_REG ECapReg;
+ VTD_IQA_REG IqaReg;
UINTN VtdUnitBaseAddress;
VtdUnitBaseAddress = VTdUnitInfo->VtdUnitBaseAddress;
@@ -121,20 +122,32 @@ PerpareCacheInvalidationInterface (
//
// Setup the IQ address, size and descriptor width through the Invalidation Queue Address Register
//
- if (VTdUnitInfo->QiDesc == NULL) {
+ if (VTdUnitInfo->QiDescBuffer == NULL) {
+ //
+ // It uses 256-bit descriptor
+ // Queue size is 128.
+ //
+ DescriptorWidth = 1;
QueueSize = 0;
- VTdUnitInfo->QiDescLength = 1 << (QueueSize + 8);
- VTdUnitInfo->QiDesc = (QI_DESC *) AllocatePages (EFI_SIZE_TO_PAGES (sizeof (QI_DESC) * VTdUnitInfo->QiDescLength));
- if (VTdUnitInfo->QiDesc == NULL) {
+
+ VTdUnitInfo->QiDescBufferSize = (sizeof (QI_256_DESC) * ((UINTN) 1 << (QueueSize + 7)));
+ VTdUnitInfo->QiDescBuffer = AllocatePages (EFI_SIZE_TO_PAGES (VTdUnitInfo->QiDescBufferSize));
+ if (VTdUnitInfo->QiDescBuffer == NULL) {
DEBUG ((DEBUG_ERROR,"Could not Alloc Invalidation Queue Buffer.\n"));
return EFI_OUT_OF_RESOURCES;
}
}
- DEBUG ((DEBUG_INFO, "Invalidation Queue Length : %d\n", VTdUnitInfo->QiDescLength));
- Reg64 = (UINT64) (UINTN) VTdUnitInfo->QiDesc;
- Reg64 |= QueueSize;
- MmioWrite64 (VtdUnitBaseAddress + R_IQA_REG, Reg64);
+ DEBUG ((DEBUG_INFO, "Invalidation Queue Buffer Size : %d\n", VTdUnitInfo->QiDescBufferSize));
+ //
+ // 4KB Aligned address
+ //
+ IqaReg.Uint64 = (UINT64) (UINTN) VTdUnitInfo->QiDescBuffer;
+ IqaReg.Bits.DW = DescriptorWidth;
+ IqaReg.Bits.QS = QueueSize;
+ MmioWrite64 (VtdUnitBaseAddress + R_IQA_REG, IqaReg.Uint64);
+ IqaReg.Uint64 = MmioRead64 (VtdUnitBaseAddress + R_IQA_REG);
+ DEBUG ((DEBUG_INFO, "IQA_REG [0x%x]\n", IqaReg.Uint64));
//
// Enable the queued invalidation interface through the Global Command Register.
@@ -148,8 +161,6 @@ PerpareCacheInvalidationInterface (
Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
} while ((Reg32 & B_GSTS_REG_QIES) == 0);
- VTdUnitInfo->QiFreeHead = 0;
-
return EFI_SUCCESS;
}
@@ -174,10 +185,10 @@ DisableQueuedInvalidationInterface (
Reg32 = MmioRead32 (VTdUnitInfo->VtdUnitBaseAddress + R_GSTS_REG);
} while ((Reg32 & B_GSTS_REG_QIES) != 0);
- if (VTdUnitInfo->QiDesc != NULL) {
- FreePages(VTdUnitInfo->QiDesc, EFI_SIZE_TO_PAGES (sizeof (QI_DESC) * VTdUnitInfo->QiDescLength));
- VTdUnitInfo->QiDesc = NULL;
- VTdUnitInfo->QiDescLength = 0;
+ if (VTdUnitInfo->QiDescBuffer != NULL) {
+ FreePages(VTdUnitInfo->QiDescBuffer, EFI_SIZE_TO_PAGES (VTdUnitInfo->QiDescBufferSize));
+ VTdUnitInfo->QiDescBuffer = NULL;
+ VTdUnitInfo->QiDescBufferSize = 0;
}
VTdUnitInfo->EnableQueuedInvalidation = 0;
@@ -197,12 +208,15 @@ QueuedInvalidationCheckFault (
IN VTD_UNIT_INFO *VTdUnitInfo
)
{
- UINT32 FaultReg;
+ UINT32 FaultReg;
+ VTD_IQERCD_REG IqercdReg;
FaultReg = MmioRead32 (VTdUnitInfo->VtdUnitBaseAddress + R_FSTS_REG);
if (FaultReg & (B_FSTS_REG_IQE | B_FSTS_REG_ITE | B_FSTS_REG_ICE)) {
- DEBUG((DEBUG_ERROR, "Detect Queue Invalidation Error [0x%08x]\n", FaultReg));
- FaultReg |= (B_FSTS_REG_IQE | B_FSTS_REG_ITE | B_FSTS_REG_ICE);
+ IqercdReg.Uint64 = MmioRead64 (VTdUnitInfo->VtdUnitBaseAddress + R_IQERCD_REG);
+
+ DEBUG((DEBUG_ERROR, "Detect Queue Invalidation Error [0x%08x] - IQERCD [0x%016lx]\n", FaultReg, IqercdReg.Uint64));
+
MmioWrite32 (VTdUnitInfo->VtdUnitBaseAddress + R_FSTS_REG, FaultReg);
return RETURN_DEVICE_ERROR;
}
@@ -223,37 +237,82 @@ QueuedInvalidationCheckFault (
**/
EFI_STATUS
SubmitQueuedInvalidationDescriptor (
- IN VTD_UNIT_INFO *VTdUnitInfo,
- IN QI_DESC *Desc
+ IN VTD_UNIT_INFO *VTdUnitInfo,
+ IN QI_256_DESC *Desc
)
{
- EFI_STATUS Status;
- UINT16 QiDescLength;
- QI_DESC *BaseDesc;
- UINT64 Reg64Iqt;
- UINT64 Reg64Iqh;
+ EFI_STATUS Status;
+ UINTN VtdUnitBaseAddress;
+ UINTN QueueSize;
+ UINTN QueueTail;
+ UINTN QueueHead;
+ QI_DESC *Qi128Desc;
+ QI_256_DESC *Qi256Desc;
+ VTD_IQA_REG IqaReg;
+ VTD_IQT_REG IqtReg;
+ VTD_IQH_REG IqhReg;
if (Desc == NULL) {
return EFI_INVALID_PARAMETER;
}
- QiDescLength = VTdUnitInfo->QiDescLength;
- BaseDesc = VTdUnitInfo->QiDesc;
-
- DEBUG((DEBUG_INFO, "[0x%x] Submit QI Descriptor [0x%016lx, 0x%016lx]\n", VTdUnitInfo->VtdUnitBaseAddress, Desc->Low, Desc->High));
-
- BaseDesc[VTdUnitInfo->QiFreeHead].Low = Desc->Low;
- BaseDesc[VTdUnitInfo->QiFreeHead].High = Desc->High;
- FlushPageTableMemory(VTdUnitInfo, (UINTN) &BaseDesc[VTdUnitInfo->QiFreeHead], sizeof(QI_DESC));
+ VtdUnitBaseAddress = VTdUnitInfo->VtdUnitBaseAddress;
+ IqaReg.Uint64 = MmioRead64 (VtdUnitBaseAddress + R_IQA_REG);
+ if (IqaReg.Bits.IQA == 0) {
+ return EFI_NOT_READY;
+ }
+ IqtReg.Uint64 = MmioRead64 (VtdUnitBaseAddress + R_IQT_REG);
- DEBUG((DEBUG_INFO,"QI Free Head=0x%x\n", VTdUnitInfo->QiFreeHead));
- VTdUnitInfo->QiFreeHead = (VTdUnitInfo->QiFreeHead + 1) % QiDescLength;
+ if (IqaReg.Bits.DW == 0) {
+ //
+ // 128-bit descriptor
+ //
+ QueueSize = (UINTN) (1 << (IqaReg.Bits.QS + 8));
+ Qi128Desc = (QI_DESC *) (UINTN) (IqaReg.Bits.IQA << VTD_PAGE_SHIFT);
+ QueueTail = (UINTN) IqtReg.Bits128Desc.QT;
+ Qi128Desc += QueueTail;
+ Qi128Desc->Low = Desc->Uint64[0];
+ Qi128Desc->High = Desc->Uint64[1];
+ FlushPageTableMemory (VTdUnitInfo, (UINTN) Qi128Desc, sizeof(QI_DESC));
+ QueueTail = (QueueTail + 1) % QueueSize;
+
+ DEBUG ((DEBUG_INFO, "[0x%x] Submit QI Descriptor 0x%x [0x%016lx, 0x%016lx]\n",
+ VtdUnitBaseAddress,
+ QueueTail,
+ Desc->Uint64[0],
+ Desc->Uint64[1]));
+
+ IqtReg.Bits128Desc.QT = QueueTail;
+ } else {
+ //
+ // 256-bit descriptor
+ //
+ QueueSize = (UINTN) (1 << (IqaReg.Bits.QS + 7));
+ Qi256Desc = (QI_256_DESC *) (UINTN) (IqaReg.Bits.IQA << VTD_PAGE_SHIFT);
+ QueueTail = (UINTN) IqtReg.Bits256Desc.QT;
+ Qi256Desc += QueueTail;
+ Qi256Desc->Uint64[0] = Desc->Uint64[0];
+ Qi256Desc->Uint64[1] = Desc->Uint64[1];
+ Qi256Desc->Uint64[2] = Desc->Uint64[2];
+ Qi256Desc->Uint64[3] = Desc->Uint64[3];
+ FlushPageTableMemory (VTdUnitInfo, (UINTN) Qi256Desc, sizeof(QI_256_DESC));
+ QueueTail = (QueueTail + 1) % QueueSize;
+
+ DEBUG ((DEBUG_INFO, "[0x%x] Submit QI Descriptor 0x%x [0x%016lx, 0x%016lx, 0x%016lx, 0x%016lx]\n",
+ VtdUnitBaseAddress,
+ QueueTail,
+ Desc->Uint64[0],
+ Desc->Uint64[1],
+ Desc->Uint64[2],
+ Desc->Uint64[3]));
+
+ IqtReg.Bits256Desc.QT = QueueTail;
+ }
//
// Update the HW tail register indicating the presence of new descriptors.
//
- Reg64Iqt = VTdUnitInfo->QiFreeHead << DMAR_IQ_SHIFT;
- MmioWrite64 (VTdUnitInfo->VtdUnitBaseAddress + R_IQT_REG, Reg64Iqt);
+ MmioWrite64 (VtdUnitBaseAddress + R_IQT_REG, IqtReg.Uint64);
Status = EFI_SUCCESS;
do {
@@ -263,10 +322,15 @@ SubmitQueuedInvalidationDescriptor (
break;
}
- Reg64Iqh = MmioRead64 (VTdUnitInfo->VtdUnitBaseAddress + R_IQH_REG);
- } while (Reg64Iqt != Reg64Iqh);
+ IqhReg.Uint64 = MmioRead64 (VtdUnitBaseAddress + R_IQH_REG);
+ if (IqaReg.Bits.DW == 0) {
+ QueueHead = (UINTN) IqhReg.Bits128Desc.QH;
+ } else {
+ QueueHead = (UINTN) IqhReg.Bits256Desc.QH;
+ }
+ } while (QueueTail != QueueHead);
- DEBUG((DEBUG_ERROR,"SubmitQueuedInvalidationDescriptor end\n"));
+ DEBUG((DEBUG_INFO,"SubmitQueuedInvalidationDescriptor end\n"));
return Status;
}
@@ -281,7 +345,7 @@ InvalidateContextCache (
)
{
UINT64 Reg64;
- QI_DESC QiDesc;
+ QI_256_DESC QiDesc;
if (VTdUnitInfo->EnableQueuedInvalidation == 0) {
//
@@ -304,8 +368,10 @@ InvalidateContextCache (
//
// Queued Invalidation
//
- QiDesc.Low = QI_CC_FM(0) | QI_CC_SID(0) | QI_CC_DID(0) | QI_CC_GRAN(1) | QI_CC_TYPE;
- QiDesc.High = 0;
+ QiDesc.Uint64[0] = QI_CC_FM(0) | QI_CC_SID(0) | QI_CC_DID(0) | QI_CC_GRAN(1) | QI_CC_TYPE;
+ QiDesc.Uint64[1] = 0;
+ QiDesc.Uint64[2] = 0;
+ QiDesc.Uint64[3] = 0;
return SubmitQueuedInvalidationDescriptor(VTdUnitInfo, &QiDesc);
}
@@ -326,7 +392,7 @@ InvalidateIOTLB (
UINT64 Reg64;
VTD_ECAP_REG ECapReg;
VTD_CAP_REG CapReg;
- QI_DESC QiDesc;
+ QI_256_DESC QiDesc;
if (VTdUnitInfo->EnableQueuedInvalidation == 0) {
//
@@ -352,8 +418,10 @@ InvalidateIOTLB (
// Queued Invalidation
//
CapReg.Uint64 = MmioRead64 (VTdUnitInfo->VtdUnitBaseAddress + R_CAP_REG);
- QiDesc.Low = QI_IOTLB_DID(0) | QI_IOTLB_DR(CAP_READ_DRAIN(CapReg.Uint64)) | QI_IOTLB_DW(CAP_WRITE_DRAIN(CapReg.Uint64)) | QI_IOTLB_GRAN(1) | QI_IOTLB_TYPE;
- QiDesc.High = QI_IOTLB_ADDR(0) | QI_IOTLB_IH(0) | QI_IOTLB_AM(0);
+ QiDesc.Uint64[0] = QI_IOTLB_DID(0) | QI_IOTLB_DR(CAP_READ_DRAIN(CapReg.Uint64)) | QI_IOTLB_DW(CAP_WRITE_DRAIN(CapReg.Uint64)) | QI_IOTLB_GRAN(1) | QI_IOTLB_TYPE;
+ QiDesc.Uint64[1] = QI_IOTLB_ADDR(0) | QI_IOTLB_IH(0) | QI_IOTLB_AM(0);
+ QiDesc.Uint64[2] = 0;
+ QiDesc.Uint64[3] = 0;
return SubmitQueuedInvalidationDescriptor(VTdUnitInfo, &QiDesc);
}
@@ -451,11 +519,6 @@ EnableDmarPreMem (
Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
DEBUG ((DEBUG_INFO, "EnableDmarPreMem: R_GSTS_REG = 0x%x \n", Reg32));
- //
- // Init DMAr Fault Event and Data registers
- //
- Reg32 = MmioRead32 (VtdUnitBaseAddress + R_FEDATA_REG);
-
//
// Write Buffer Flush
//
@@ -525,11 +588,6 @@ EnableDmar (
DEBUG ((DEBUG_INFO, "EnableDmar: waiting for RTPS bit to be set... \n"));
SetGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_REG_SRTP);
- //
- // Init DMAr Fault Event and Data registers
- //
- MmioRead32 (VtdUnitBaseAddress + R_FEDATA_REG);
-
//
// Write Buffer Flush before invalidation
//
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmarPei.h b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmarPei.h
index 5ade9ec35..4d4b912f2 100644
--- a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmarPei.h
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmarPei.h
@@ -21,9 +21,8 @@ typedef struct {
VTD_ECAP_REG ECapReg;
BOOLEAN Is5LevelPaging;
UINT8 EnableQueuedInvalidation;
- UINT16 QiDescLength;
- QI_DESC *QiDesc;
- UINT16 QiFreeHead;
+ VOID *QiDescBuffer;
+ UINTN QiDescBufferSize;
UINTN FixedSecondLevelPagingEntry;
UINTN RootEntryTable;
UINTN ExtRootEntryTable;
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.c
index 628565ee7..878c952b7 100644
--- a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.c
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.c
@@ -496,6 +496,9 @@ SetupVtd (
if (EFI_ERROR (Status)) {
return;
}
+
+ DumpVtdIfError ();
+
DEBUG ((DEBUG_INFO, "PrepareVtdConfig\n"));
PrepareVtdConfig ();
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.h b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.h
index 7dd29a243..e83ebff41 100644
--- a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.h
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.h
@@ -81,9 +81,8 @@ typedef struct {
PCI_DEVICE_INFORMATION PciDeviceInfo;
BOOLEAN Is5LevelPaging;
UINT8 EnableQueuedInvalidation;
- UINT16 QiDescLength;
- QI_DESC *QiDesc;
- UINT16 QiFreeHead;
+ VOID *QiDescBuffer;
+ UINTN QiDescBufferSize;
} VTD_UNIT_INFORMATION;
//
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/VtdReg.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/VtdReg.c
index 8e834f4c4..7e45ac2d2 100644
--- a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/VtdReg.c
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/VtdReg.c
@@ -68,71 +68,87 @@ PerpareCacheInvalidationInterface (
IN UINTN VtdIndex
)
{
- UINT16 QueueSize;
- UINT64 Reg64;
- UINT32 Reg32;
-
- if (mVtdUnitInformation[VtdIndex].VerReg.Bits.Major <= 5) {
- mVtdUnitInformation[VtdIndex].EnableQueuedInvalidation = 0;
+ UINT8 DescriptorWidth;
+ UINTN QueueSize;
+ UINT32 Reg32;
+ VTD_IQA_REG IqaReg;
+ VTD_UNIT_INFORMATION *VTdUnitInfo;
+ UINTN VtdUnitBaseAddress;
+
+ VTdUnitInfo = &mVtdUnitInformation[VtdIndex];
+ VtdUnitBaseAddress = VTdUnitInfo->VtdUnitBaseAddress;
+
+ if (VTdUnitInfo->VerReg.Bits.Major <= 5) {
+ VTdUnitInfo->EnableQueuedInvalidation = 0;
DEBUG ((DEBUG_INFO, "Use Register-based Invalidation Interface for engine [%d]\n", VtdIndex));
return EFI_SUCCESS;
}
- if (mVtdUnitInformation[VtdIndex].ECapReg.Bits.QI == 0) {
+ if (VTdUnitInfo->ECapReg.Bits.QI == 0) {
DEBUG ((DEBUG_ERROR, "Hardware does not support queued invalidations interface for engine [%d]\n", VtdIndex));
return EFI_UNSUPPORTED;
}
- mVtdUnitInformation[VtdIndex].EnableQueuedInvalidation = 1;
+ VTdUnitInfo->EnableQueuedInvalidation = 1;
DEBUG ((DEBUG_INFO, "Use Queued Invalidation Interface for engine [%d]\n", VtdIndex));
- Reg32 = MmioRead32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_GSTS_REG);
+ Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
if ((Reg32 & B_GSTS_REG_QIES) != 0) {
DEBUG ((DEBUG_ERROR,"Queued Invalidation Interface was enabled.\n"));
Reg32 &= (~B_GSTS_REG_QIES);
- MmioWrite32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_GCMD_REG, Reg32);
+ MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, Reg32);
do {
- Reg32 = MmioRead32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_GSTS_REG);
+ Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
} while ((Reg32 & B_GSTS_REG_QIES) != 0);
}
//
// Initialize the Invalidation Queue Tail Register to zero.
//
- MmioWrite64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_IQT_REG, 0);
+ MmioWrite64 (VtdUnitBaseAddress + R_IQT_REG, 0);
//
// Setup the IQ address, size and descriptor width through the Invalidation Queue Address Register
//
- QueueSize = 0;
- mVtdUnitInformation[VtdIndex].QiDescLength = 1 << (QueueSize + 8);
- mVtdUnitInformation[VtdIndex].QiDesc = (QI_DESC *) AllocatePages (EFI_SIZE_TO_PAGES(sizeof(QI_DESC) * mVtdUnitInformation[VtdIndex].QiDescLength));
-
- if (mVtdUnitInformation[VtdIndex].QiDesc == NULL) {
- mVtdUnitInformation[VtdIndex].QiDescLength = 0;
- DEBUG ((DEBUG_ERROR,"Could not Alloc Invalidation Queue Buffer.\n"));
- return EFI_OUT_OF_RESOURCES;
+ if (VTdUnitInfo->QiDescBuffer == NULL) {
+ //
+ // It uses 256-bit descriptor
+ // Queue size is 128.
+ //
+ DescriptorWidth = 1;
+ QueueSize = 0;
+
+ VTdUnitInfo->QiDescBufferSize = (sizeof (QI_256_DESC) * ((UINTN) 1 << (QueueSize + 7)));
+ VTdUnitInfo->QiDescBuffer = AllocatePages (EFI_SIZE_TO_PAGES (VTdUnitInfo->QiDescBufferSize));
+ if (VTdUnitInfo->QiDescBuffer == NULL) {
+ DEBUG ((DEBUG_ERROR,"Could not Alloc Invalidation Queue Buffer.\n"));
+ return EFI_OUT_OF_RESOURCES;
+ }
}
- DEBUG ((DEBUG_INFO, "Invalidation Queue Length : %d\n", mVtdUnitInformation[VtdIndex].QiDescLength));
- Reg64 = (UINT64)(UINTN)mVtdUnitInformation[VtdIndex].QiDesc;
- Reg64 |= QueueSize;
- MmioWrite64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_IQA_REG, Reg64);
+ DEBUG ((DEBUG_INFO, "Invalidation Queue Buffer Size : %d\n", VTdUnitInfo->QiDescBufferSize));
+ //
+ // 4KB Aligned address
+ //
+ IqaReg.Uint64 = (UINT64) (UINTN) VTdUnitInfo->QiDescBuffer;
+ IqaReg.Bits.DW = DescriptorWidth;
+ IqaReg.Bits.QS = QueueSize;
+ MmioWrite64 (VtdUnitBaseAddress + R_IQA_REG, IqaReg.Uint64);
+ IqaReg.Uint64 = MmioRead64 (VtdUnitBaseAddress + R_IQA_REG);
+ DEBUG ((DEBUG_INFO, "IQA_REG [0x%x]\n", IqaReg.Uint64));
//
// Enable the queued invalidation interface through the Global Command Register.
// When enabled, hardware sets the QIES field in the Global Status Register.
//
- Reg32 = MmioRead32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_GSTS_REG);
+ Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
Reg32 |= B_GMCD_REG_QIE;
- MmioWrite32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_GCMD_REG, Reg32);
+ MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, Reg32);
DEBUG ((DEBUG_INFO, "Enable Queued Invalidation Interface. GCMD_REG = 0x%x\n", Reg32));
do {
- Reg32 = MmioRead32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_GSTS_REG);
+ Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
} while ((Reg32 & B_GSTS_REG_QIES) == 0);
- mVtdUnitInformation[VtdIndex].QiFreeHead = 0;
-
return EFI_SUCCESS;
}
@@ -146,21 +162,24 @@ DisableQueuedInvalidationInterface (
IN UINTN VtdIndex
)
{
- UINT32 Reg32;
+ UINT32 Reg32;
+ VTD_UNIT_INFORMATION *VTdUnitInfo;
- if (mVtdUnitInformation[VtdIndex].EnableQueuedInvalidation != 0) {
- Reg32 = MmioRead32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_GSTS_REG);
+ VTdUnitInfo = &mVtdUnitInformation[VtdIndex];
+
+ if (VTdUnitInfo->EnableQueuedInvalidation != 0) {
+ Reg32 = MmioRead32 (VTdUnitInfo->VtdUnitBaseAddress + R_GSTS_REG);
Reg32 &= (~B_GMCD_REG_QIE);
- MmioWrite32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_GCMD_REG, Reg32);
+ MmioWrite32 (VTdUnitInfo->VtdUnitBaseAddress + R_GCMD_REG, Reg32);
DEBUG ((DEBUG_INFO, "Disable Queued Invalidation Interface. GCMD_REG = 0x%x\n", Reg32));
do {
- Reg32 = MmioRead32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_GSTS_REG);
+ Reg32 = MmioRead32 (VTdUnitInfo->VtdUnitBaseAddress + R_GSTS_REG);
} while ((Reg32 & B_GSTS_REG_QIES) != 0);
- if (mVtdUnitInformation[VtdIndex].QiDesc != NULL) {
- FreePages(mVtdUnitInformation[VtdIndex].QiDesc, EFI_SIZE_TO_PAGES(sizeof(QI_DESC) * mVtdUnitInformation[VtdIndex].QiDescLength));
- mVtdUnitInformation[VtdIndex].QiDesc = NULL;
- mVtdUnitInformation[VtdIndex].QiDescLength = 0;
+ if (VTdUnitInfo->QiDescBuffer != NULL) {
+ FreePages(VTdUnitInfo->QiDescBuffer, EFI_SIZE_TO_PAGES (VTdUnitInfo->QiDescBufferSize));
+ VTdUnitInfo->QiDescBuffer = NULL;
+ VTdUnitInfo->QiDescBufferSize = 0;
}
mVtdUnitInformation[VtdIndex].EnableQueuedInvalidation = 0;
@@ -180,27 +199,16 @@ QueuedInvalidationCheckFault (
IN UINTN VtdIndex
)
{
- UINT32 FaultReg;
+ UINT32 FaultReg;
+ VTD_IQERCD_REG IqercdReg;
FaultReg = MmioRead32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_FSTS_REG);
- if (FaultReg & B_FSTS_REG_IQE) {
- DEBUG((DEBUG_ERROR, "Detect Invalidation Queue Error [0x%08x]\n", FaultReg));
- FaultReg |= B_FSTS_REG_IQE;
- MmioWrite32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_FSTS_REG, FaultReg);
- return RETURN_DEVICE_ERROR;
- }
+ if (FaultReg & (B_FSTS_REG_IQE | B_FSTS_REG_ITE | B_FSTS_REG_ICE)) {
+ IqercdReg.Uint64 = MmioRead64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_IQERCD_REG);
- if (FaultReg & B_FSTS_REG_ITE) {
- DEBUG((DEBUG_ERROR, "Detect Invalidation Time-out Error [0x%08x]\n", FaultReg));
- FaultReg |= B_FSTS_REG_ITE;
- MmioWrite32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_FSTS_REG, FaultReg);
- return RETURN_DEVICE_ERROR;
- }
+ DEBUG((DEBUG_ERROR, "Detect Queue Invalidation Error [0x%08x] - IQERCD [0x%016lx]\n", FaultReg, IqercdReg.Uint64));
- if (FaultReg & B_FSTS_REG_ICE) {
- DEBUG((DEBUG_ERROR, "Detect Invalidation Completion Error [0x%08x]\n", FaultReg));
- FaultReg |= B_FSTS_REG_ICE;
MmioWrite32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_FSTS_REG, FaultReg);
return RETURN_DEVICE_ERROR;
}
@@ -221,36 +229,82 @@ QueuedInvalidationCheckFault (
**/
EFI_STATUS
SubmitQueuedInvalidationDescriptor (
- IN UINTN VtdIndex,
- IN QI_DESC *Desc
+ IN UINTN VtdIndex,
+ IN QI_256_DESC *Desc
)
{
- EFI_STATUS Status;
- UINT16 QiDescLength;
- QI_DESC *BaseDesc;
- UINT64 Reg64Iqt;
- UINT64 Reg64Iqh;
+ EFI_STATUS Status;
+ UINTN VtdUnitBaseAddress;
+ UINTN QueueSize;
+ UINTN QueueTail;
+ UINTN QueueHead;
+ QI_DESC *Qi128Desc;
+ QI_256_DESC *Qi256Desc;
+ VTD_IQA_REG IqaReg;
+ VTD_IQT_REG IqtReg;
+ VTD_IQH_REG IqhReg;
if (Desc == NULL) {
return EFI_INVALID_PARAMETER;
}
- QiDescLength = mVtdUnitInformation[VtdIndex].QiDescLength;
- BaseDesc = mVtdUnitInformation[VtdIndex].QiDesc;
-
- DEBUG((DEBUG_VERBOSE, "[%d] Submit QI Descriptor [0x%08x, 0x%08x] Free Head (%d)\n", VtdIndex, Desc->Low, Desc->High, mVtdUnitInformation[VtdIndex].QiFreeHead));
-
- BaseDesc[mVtdUnitInformation[VtdIndex].QiFreeHead].Low = Desc->Low;
- BaseDesc[mVtdUnitInformation[VtdIndex].QiFreeHead].High = Desc->High;
- FlushPageTableMemory(VtdIndex, (UINTN) &BaseDesc[mVtdUnitInformation[VtdIndex].QiFreeHead], sizeof(QI_DESC));
+ VtdUnitBaseAddress = mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress;
+ IqaReg.Uint64 = MmioRead64 (VtdUnitBaseAddress + R_IQA_REG);
+ if (IqaReg.Bits.IQA == 0) {
+ return EFI_NOT_READY;
+ }
+ IqtReg.Uint64 = MmioRead64 (VtdUnitBaseAddress + R_IQT_REG);
- mVtdUnitInformation[VtdIndex].QiFreeHead = (mVtdUnitInformation[VtdIndex].QiFreeHead + 1) % QiDescLength;
+ if (IqaReg.Bits.DW == 0) {
+ //
+ // 128-bit descriptor
+ //
+ QueueSize = (UINTN) (1 << (IqaReg.Bits.QS + 8));
+ Qi128Desc = (QI_DESC *) (UINTN) (IqaReg.Bits.IQA << VTD_PAGE_SHIFT);
+ QueueTail = (UINTN) IqtReg.Bits128Desc.QT;
+ Qi128Desc += QueueTail;
+ Qi128Desc->Low = Desc->Uint64[0];
+ Qi128Desc->High = Desc->Uint64[1];
+ FlushPageTableMemory (VtdIndex, (UINTN) Qi128Desc, sizeof(QI_DESC));
+ QueueTail = (QueueTail + 1) % QueueSize;
+
+ DEBUG ((DEBUG_VERBOSE, "[0x%x] Submit QI Descriptor 0x%x [0x%016lx, 0x%016lx]\n",
+ VtdUnitBaseAddress,
+ QueueTail,
+ Desc->Uint64[0],
+ Desc->Uint64[1]));
+
+ IqtReg.Bits128Desc.QT = QueueTail;
+ } else {
+ //
+ // 256-bit descriptor
+ //
+ QueueSize = (UINTN) (1 << (IqaReg.Bits.QS + 7));
+ Qi256Desc = (QI_256_DESC *) (UINTN) (IqaReg.Bits.IQA << VTD_PAGE_SHIFT);
+ QueueTail = (UINTN) IqtReg.Bits256Desc.QT;
+ Qi256Desc += QueueTail;
+ Qi256Desc->Uint64[0] = Desc->Uint64[0];
+ Qi256Desc->Uint64[1] = Desc->Uint64[1];
+ Qi256Desc->Uint64[2] = Desc->Uint64[2];
+ Qi256Desc->Uint64[3] = Desc->Uint64[3];
+ FlushPageTableMemory (VtdIndex, (UINTN) Qi256Desc, sizeof(QI_256_DESC));
+ QueueTail = (QueueTail + 1) % QueueSize;
+
+ DEBUG ((DEBUG_VERBOSE, "[0x%x] Submit QI Descriptor 0x%x [0x%016lx, 0x%016lx, 0x%016lx, 0x%016lx]\n",
+ VtdUnitBaseAddress,
+ QueueTail,
+ Desc->Uint64[0],
+ Desc->Uint64[1],
+ Desc->Uint64[2],
+ Desc->Uint64[3]));
+
+ IqtReg.Bits256Desc.QT = QueueTail;
+ }
//
// Update the HW tail register indicating the presence of new descriptors.
//
- Reg64Iqt = mVtdUnitInformation[VtdIndex].QiFreeHead << DMAR_IQ_SHIFT;
- MmioWrite64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_IQT_REG, Reg64Iqt);
+ MmioWrite64 (VtdUnitBaseAddress + R_IQT_REG, IqtReg.Uint64);
Status = EFI_SUCCESS;
do {
@@ -260,8 +314,13 @@ SubmitQueuedInvalidationDescriptor (
break;
}
- Reg64Iqh = MmioRead64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_IQH_REG);
- } while (Reg64Iqt != Reg64Iqh);
+ IqhReg.Uint64 = MmioRead64 (VtdUnitBaseAddress + R_IQH_REG);
+ if (IqaReg.Bits.DW == 0) {
+ QueueHead = (UINTN) IqhReg.Bits128Desc.QH;
+ } else {
+ QueueHead = (UINTN) IqhReg.Bits256Desc.QH;
+ }
+ } while (QueueTail != QueueHead);
return Status;
}
@@ -276,8 +335,8 @@ InvalidateContextCache (
IN UINTN VtdIndex
)
{
- UINT64 Reg64;
- QI_DESC QiDesc;
+ UINT64 Reg64;
+ QI_256_DESC QiDesc;
if (mVtdUnitInformation[VtdIndex].EnableQueuedInvalidation == 0) {
//
@@ -300,8 +359,10 @@ InvalidateContextCache (
//
// Queued Invalidation
//
- QiDesc.Low = QI_CC_FM(0) | QI_CC_SID(0) | QI_CC_DID(0) | QI_CC_GRAN(1) | QI_CC_TYPE;
- QiDesc.High = 0;
+ QiDesc.Uint64[0] = QI_CC_FM(0) | QI_CC_SID(0) | QI_CC_DID(0) | QI_CC_GRAN(1) | QI_CC_TYPE;
+ QiDesc.Uint64[1] = 0;
+ QiDesc.Uint64[2] = 0;
+ QiDesc.Uint64[3] = 0;
return SubmitQueuedInvalidationDescriptor(VtdIndex, &QiDesc);
}
@@ -318,8 +379,8 @@ InvalidateIOTLB (
IN UINTN VtdIndex
)
{
- UINT64 Reg64;
- QI_DESC QiDesc;
+ UINT64 Reg64;
+ QI_256_DESC QiDesc;
if (mVtdUnitInformation[VtdIndex].EnableQueuedInvalidation == 0) {
//
@@ -342,8 +403,10 @@ InvalidateIOTLB (
//
// Queued Invalidation
//
- QiDesc.Low = QI_IOTLB_DID(0) | QI_IOTLB_DR(CAP_READ_DRAIN(mVtdUnitInformation[VtdIndex].CapReg.Uint64)) | QI_IOTLB_DW(CAP_WRITE_DRAIN(mVtdUnitInformation[VtdIndex].CapReg.Uint64)) | QI_IOTLB_GRAN(1) | QI_IOTLB_TYPE;
- QiDesc.High = QI_IOTLB_ADDR(0) | QI_IOTLB_IH(0) | QI_IOTLB_AM(0);
+ QiDesc.Uint64[0] = QI_IOTLB_DID(0) | QI_IOTLB_DR(CAP_READ_DRAIN(mVtdUnitInformation[VtdIndex].CapReg.Uint64)) | QI_IOTLB_DW(CAP_WRITE_DRAIN(mVtdUnitInformation[VtdIndex].CapReg.Uint64)) | QI_IOTLB_GRAN(1) | QI_IOTLB_TYPE;
+ QiDesc.Uint64[1] = QI_IOTLB_ADDR(0) | QI_IOTLB_IH(0) | QI_IOTLB_AM(0);
+ QiDesc.Uint64[2] = 0;
+ QiDesc.Uint64[3] = 0;
return SubmitQueuedInvalidationDescriptor(VtdIndex, &QiDesc);
}
@@ -611,11 +674,6 @@ EnableDmar (
DEBUG((DEBUG_INFO, "EnableDmar: waiting for RTPS bit to be set... \n"));
SetGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_REG_SRTP);
- //
- // Init DMAr Fault Event and Data registers
- //
- MmioRead32 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_FEDATA_REG);
-
//
// Write Buffer Flush before invalidation
//
diff --git a/Silicon/Intel/IntelSiliconPkg/Include/IndustryStandard/Vtd.h b/Silicon/Intel/IntelSiliconPkg/Include/IndustryStandard/Vtd.h
index 32fbdd02e..3e1b8c3c5 100644
--- a/Silicon/Intel/IntelSiliconPkg/Include/IndustryStandard/Vtd.h
+++ b/Silicon/Intel/IntelSiliconPkg/Include/IndustryStandard/Vtd.h
@@ -259,6 +259,8 @@ typedef union {
#define R_IQA_REG 0x90
+#define R_IQERCD_REG 0xB0
+
#define VTD_PAGE_SHIFT (12)
#define VTD_PAGE_SIZE (1UL << VTD_PAGE_SHIFT)
#define VTD_PAGE_MASK (((UINT64)-1) << VTD_PAGE_SHIFT)
@@ -289,13 +291,20 @@ typedef union {
#define QI_IWD_STATUS_WRITE (((UINT64)1) << 5)
//
-// This is the queued invalidate descriptor.
+// queued invalidation 128-bit descriptor
//
typedef struct {
- UINT64 Low;
- UINT64 High;
+ UINT64 Low;
+ UINT64 High;
} QI_DESC;
+//
+// queued invalidation 256-bit descriptor
+//
+typedef struct {
+ UINT64 Uint64[4];
+} QI_256_DESC;
+
typedef union {
struct {
UINT8 Minor:4;
@@ -411,6 +420,56 @@ typedef union {
UINT64 Uint64[2];
} VTD_FRCD_REG;
+typedef union {
+ struct {
+ UINT32 IQEI:4; // Invalidation Queue Error Info
+ UINT32 Rsvd_4:28;
+ UINT32 ITESID:16; // Invalidation Time-out Error Source Identifier
+ UINT32 ICESID:16; // Invalidation Completion Error Source Identifier
+ } Bits;
+ UINT64 Uint64;
+} VTD_IQERCD_REG;
+
+typedef union {
+ struct {
+ UINT64 Rsvd_0:4;
+ UINT64 QH:15; // Queue Head
+ UINT64 Rsvd_19:45;
+ } Bits128Desc;
+ struct {
+ UINT64 Rsvd_0:4;
+ UINT64 Rsvd_4:1;
+ UINT64 QH:14; // Queue Head
+ UINT64 Rsvd_19:45;
+ } Bits256Desc;
+ UINT64 Uint64;
+} VTD_IQH_REG;
+
+typedef union {
+ struct {
+ UINT64 Rsvd_0:4;
+ UINT64 QT:15; // Queue Tail
+ UINT64 Rsvd_19:45;
+ } Bits128Desc;
+ struct {
+ UINT64 Rsvd_0:4;
+ UINT64 Rsvd_4:1;
+ UINT64 QT:14; // Queue Tail
+ UINT64 Rsvd_19:45;
+ } Bits256Desc;
+ UINT64 Uint64;
+} VTD_IQT_REG;
+
+typedef union {
+ struct {
+ UINT64 QS:3; // Queue Size
+ UINT64 Rsvd_3:8;
+ UINT64 DW:1; // Descriptor Width
+ UINT64 IQA:52; // Invalidation Queue Base Address
+ } Bits;
+ UINT64 Uint64;
+} VTD_IQA_REG;
+
typedef union {
struct {
UINT8 Function:3;
--
2.26.2.windows.1
^ permalink raw reply related [flat|nested] 2+ messages in thread
* [PATCH] IntelSiliconPkg/VTd: Use 256-bit invaildation queue descriptor
@ 2022-11-30 5:15 Sheng Wei
0 siblings, 0 replies; 2+ messages in thread
From: Sheng Wei @ 2022-11-30 5:15 UTC (permalink / raw)
To: devel; +Cc: Ray Ni, Rangasai V Chaganty, Jenny Huang, Robert Kowalewski
256-bit invaildation queue descriptor could be used for both
abort DMA mode and legacy mode.
Signed-off-by: Sheng Wei <w.sheng@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
Cc: Rangasai V Chaganty <rangasai.v.chaganty@intel.com>
Cc: Jenny Huang <jenny.huang@intel.com>
Cc: Robert Kowalewski <robert.kowalewski@intel.com>
---
.../VTd/IntelVTdDmarPei/IntelVTdDmar.c | 188 ++++++++-----
.../VTd/IntelVTdDmarPei/IntelVTdDmarPei.h | 5 +-
.../Feature/VTd/IntelVTdDxe/DmaProtection.c | 3 +
.../Feature/VTd/IntelVTdDxe/DmaProtection.h | 5 +-
.../Feature/VTd/IntelVTdDxe/VtdReg.c | 248 +++++++++++-------
.../Include/IndustryStandard/Vtd.h | 65 ++++-
6 files changed, 355 insertions(+), 159 deletions(-)
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.c
index af85a3d8e..0c9805550 100644
--- a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.c
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.c
@@ -79,10 +79,11 @@ PerpareCacheInvalidationInterface (
IN VTD_UNIT_INFO *VTdUnitInfo
)
{
- UINT16 QueueSize;
- UINT64 Reg64;
+ UINT8 DescriptorWidth;
+ UINTN QueueSize;
UINT32 Reg32;
VTD_ECAP_REG ECapReg;
+ VTD_IQA_REG IqaReg;
UINTN VtdUnitBaseAddress;
VtdUnitBaseAddress = VTdUnitInfo->VtdUnitBaseAddress;
@@ -121,20 +122,34 @@ PerpareCacheInvalidationInterface (
//
// Setup the IQ address, size and descriptor width through the Invalidation Queue Address Register
//
- if (VTdUnitInfo->QiDesc == NULL) {
+ if (VTdUnitInfo->QiDescBuffer == NULL) {
+ //
+ // It uses 256-bit descriptor
+ // Queue size is 128.
+ //
+ DescriptorWidth = 1;
QueueSize = 0;
- VTdUnitInfo->QiDescLength = 1 << (QueueSize + 8);
- VTdUnitInfo->QiDesc = (QI_DESC *) AllocatePages (EFI_SIZE_TO_PAGES (sizeof (QI_DESC) * VTdUnitInfo->QiDescLength));
- if (VTdUnitInfo->QiDesc == NULL) {
+
+ VTdUnitInfo->QiDescBufferSize = (sizeof (QI_256_DESC) * ((UINTN) 1 << (QueueSize + 7)));
+ VTdUnitInfo->QiDescBuffer = AllocatePages (EFI_SIZE_TO_PAGES (VTdUnitInfo->QiDescBufferSize));
+ if (VTdUnitInfo->QiDescBuffer == NULL) {
DEBUG ((DEBUG_ERROR,"Could not Alloc Invalidation Queue Buffer.\n"));
return EFI_OUT_OF_RESOURCES;
}
}
- DEBUG ((DEBUG_INFO, "Invalidation Queue Length : %d\n", VTdUnitInfo->QiDescLength));
- Reg64 = (UINT64) (UINTN) VTdUnitInfo->QiDesc;
- Reg64 |= QueueSize;
- MmioWrite64 (VtdUnitBaseAddress + R_IQA_REG, Reg64);
+ DEBUG ((DEBUG_INFO, "Invalidation Queue Buffer Size : %d\n", VTdUnitInfo->QiDescBufferSize));
+ //
+ // 4KB Aligned address
+ //
+ IqaReg.Uint64 = (UINT64) (UINTN) VTdUnitInfo->QiDescBuffer;
+ IqaReg.Bits.DW = DescriptorWidth;
+ IqaReg.Bits.QS = QueueSize;
+ MmioWrite64 (VtdUnitBaseAddress + R_IQA_REG, IqaReg.Uint64);
+ IqaReg.Uint64 = MmioRead64 (VtdUnitBaseAddress + R_IQA_REG);
+ DEBUG ((DEBUG_INFO, "IQA_REG [0x%lx]\n", IqaReg.Uint64));
+
+ DEBUG ((DEBUG_INFO, "IQH_REG [0x%lx]\n", MmioRead64 (VtdUnitBaseAddress + R_IQH_REG)));
//
// Enable the queued invalidation interface through the Global Command Register.
@@ -148,8 +163,6 @@ PerpareCacheInvalidationInterface (
Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
} while ((Reg32 & B_GSTS_REG_QIES) == 0);
- VTdUnitInfo->QiFreeHead = 0;
-
return EFI_SUCCESS;
}
@@ -174,10 +187,10 @@ DisableQueuedInvalidationInterface (
Reg32 = MmioRead32 (VTdUnitInfo->VtdUnitBaseAddress + R_GSTS_REG);
} while ((Reg32 & B_GSTS_REG_QIES) != 0);
- if (VTdUnitInfo->QiDesc != NULL) {
- FreePages(VTdUnitInfo->QiDesc, EFI_SIZE_TO_PAGES (sizeof (QI_DESC) * VTdUnitInfo->QiDescLength));
- VTdUnitInfo->QiDesc = NULL;
- VTdUnitInfo->QiDescLength = 0;
+ if (VTdUnitInfo->QiDescBuffer != NULL) {
+ FreePages(VTdUnitInfo->QiDescBuffer, EFI_SIZE_TO_PAGES (VTdUnitInfo->QiDescBufferSize));
+ VTdUnitInfo->QiDescBuffer = NULL;
+ VTdUnitInfo->QiDescBufferSize = 0;
}
VTdUnitInfo->EnableQueuedInvalidation = 0;
@@ -197,12 +210,15 @@ QueuedInvalidationCheckFault (
IN VTD_UNIT_INFO *VTdUnitInfo
)
{
- UINT32 FaultReg;
+ UINT32 FaultReg;
+ VTD_IQERCD_REG IqercdReg;
FaultReg = MmioRead32 (VTdUnitInfo->VtdUnitBaseAddress + R_FSTS_REG);
if (FaultReg & (B_FSTS_REG_IQE | B_FSTS_REG_ITE | B_FSTS_REG_ICE)) {
- DEBUG((DEBUG_ERROR, "Detect Queue Invalidation Error [0x%08x]\n", FaultReg));
- FaultReg |= (B_FSTS_REG_IQE | B_FSTS_REG_ITE | B_FSTS_REG_ICE);
+ IqercdReg.Uint64 = MmioRead64 (VTdUnitInfo->VtdUnitBaseAddress + R_IQERCD_REG);
+
+ DEBUG((DEBUG_ERROR, "Detect Queue Invalidation Error [0x%08x] - IQERCD [0x%016lx]\n", FaultReg, IqercdReg.Uint64));
+
MmioWrite32 (VTdUnitInfo->VtdUnitBaseAddress + R_FSTS_REG, FaultReg);
return RETURN_DEVICE_ERROR;
}
@@ -223,37 +239,83 @@ QueuedInvalidationCheckFault (
**/
EFI_STATUS
SubmitQueuedInvalidationDescriptor (
- IN VTD_UNIT_INFO *VTdUnitInfo,
- IN QI_DESC *Desc
+ IN VTD_UNIT_INFO *VTdUnitInfo,
+ IN QI_256_DESC *Desc
)
{
- EFI_STATUS Status;
- UINT16 QiDescLength;
- QI_DESC *BaseDesc;
- UINT64 Reg64Iqt;
- UINT64 Reg64Iqh;
+ EFI_STATUS Status;
+ UINTN VtdUnitBaseAddress;
+ UINTN QueueSize;
+ UINTN QueueTail;
+ UINTN QueueHead;
+ QI_DESC *Qi128Desc;
+ QI_256_DESC *Qi256Desc;
+ VTD_IQA_REG IqaReg;
+ VTD_IQT_REG IqtReg;
+ VTD_IQH_REG IqhReg;
if (Desc == NULL) {
return EFI_INVALID_PARAMETER;
}
- QiDescLength = VTdUnitInfo->QiDescLength;
- BaseDesc = VTdUnitInfo->QiDesc;
-
- DEBUG((DEBUG_INFO, "[0x%x] Submit QI Descriptor [0x%016lx, 0x%016lx]\n", VTdUnitInfo->VtdUnitBaseAddress, Desc->Low, Desc->High));
-
- BaseDesc[VTdUnitInfo->QiFreeHead].Low = Desc->Low;
- BaseDesc[VTdUnitInfo->QiFreeHead].High = Desc->High;
- FlushPageTableMemory(VTdUnitInfo, (UINTN) &BaseDesc[VTdUnitInfo->QiFreeHead], sizeof(QI_DESC));
+ VtdUnitBaseAddress = VTdUnitInfo->VtdUnitBaseAddress;
+ IqaReg.Uint64 = MmioRead64 (VtdUnitBaseAddress + R_IQA_REG);
+ if (IqaReg.Bits.IQA == 0) {
+ DEBUG ((DEBUG_ERROR,"Invalidation Queue Buffer not ready [0x%lx]\n", IqaReg.Uint64));
+ return EFI_NOT_READY;
+ }
+ IqtReg.Uint64 = MmioRead64 (VtdUnitBaseAddress + R_IQT_REG);
- DEBUG((DEBUG_INFO,"QI Free Head=0x%x\n", VTdUnitInfo->QiFreeHead));
- VTdUnitInfo->QiFreeHead = (VTdUnitInfo->QiFreeHead + 1) % QiDescLength;
+ if (IqaReg.Bits.DW == 0) {
+ //
+ // 128-bit descriptor
+ //
+ QueueSize = (UINTN) (1 << (IqaReg.Bits.QS + 8));
+ Qi128Desc = (QI_DESC *) (UINTN) (IqaReg.Bits.IQA << VTD_PAGE_SHIFT);
+ QueueTail = (UINTN) IqtReg.Bits128Desc.QT;
+ Qi128Desc += QueueTail;
+ Qi128Desc->Low = Desc->Uint64[0];
+ Qi128Desc->High = Desc->Uint64[1];
+ FlushPageTableMemory (VTdUnitInfo, (UINTN) Qi128Desc, sizeof(QI_DESC));
+ QueueTail = (QueueTail + 1) % QueueSize;
+
+ DEBUG ((DEBUG_INFO, "[0x%x] Submit QI Descriptor 0x%x [0x%016lx, 0x%016lx]\n",
+ VtdUnitBaseAddress,
+ QueueTail,
+ Desc->Uint64[0],
+ Desc->Uint64[1]));
+
+ IqtReg.Bits128Desc.QT = QueueTail;
+ } else {
+ //
+ // 256-bit descriptor
+ //
+ QueueSize = (UINTN) (1 << (IqaReg.Bits.QS + 7));
+ Qi256Desc = (QI_256_DESC *) (UINTN) (IqaReg.Bits.IQA << VTD_PAGE_SHIFT);
+ QueueTail = (UINTN) IqtReg.Bits256Desc.QT;
+ Qi256Desc += QueueTail;
+ Qi256Desc->Uint64[0] = Desc->Uint64[0];
+ Qi256Desc->Uint64[1] = Desc->Uint64[1];
+ Qi256Desc->Uint64[2] = Desc->Uint64[2];
+ Qi256Desc->Uint64[3] = Desc->Uint64[3];
+ FlushPageTableMemory (VTdUnitInfo, (UINTN) Qi256Desc, sizeof(QI_256_DESC));
+ QueueTail = (QueueTail + 1) % QueueSize;
+
+ DEBUG ((DEBUG_INFO, "[0x%x] Submit QI Descriptor 0x%x [0x%016lx, 0x%016lx, 0x%016lx, 0x%016lx]\n",
+ VtdUnitBaseAddress,
+ QueueTail,
+ Desc->Uint64[0],
+ Desc->Uint64[1],
+ Desc->Uint64[2],
+ Desc->Uint64[3]));
+
+ IqtReg.Bits256Desc.QT = QueueTail;
+ }
//
// Update the HW tail register indicating the presence of new descriptors.
//
- Reg64Iqt = VTdUnitInfo->QiFreeHead << DMAR_IQ_SHIFT;
- MmioWrite64 (VTdUnitInfo->VtdUnitBaseAddress + R_IQT_REG, Reg64Iqt);
+ MmioWrite64 (VtdUnitBaseAddress + R_IQT_REG, IqtReg.Uint64);
Status = EFI_SUCCESS;
do {
@@ -263,10 +325,15 @@ SubmitQueuedInvalidationDescriptor (
break;
}
- Reg64Iqh = MmioRead64 (VTdUnitInfo->VtdUnitBaseAddress + R_IQH_REG);
- } while (Reg64Iqt != Reg64Iqh);
+ IqhReg.Uint64 = MmioRead64 (VtdUnitBaseAddress + R_IQH_REG);
+ if (IqaReg.Bits.DW == 0) {
+ QueueHead = (UINTN) IqhReg.Bits128Desc.QH;
+ } else {
+ QueueHead = (UINTN) IqhReg.Bits256Desc.QH;
+ }
+ } while (QueueTail != QueueHead);
- DEBUG((DEBUG_ERROR,"SubmitQueuedInvalidationDescriptor end\n"));
+ DEBUG((DEBUG_INFO,"SubmitQueuedInvalidationDescriptor end\n"));
return Status;
}
@@ -281,7 +348,7 @@ InvalidateContextCache (
)
{
UINT64 Reg64;
- QI_DESC QiDesc;
+ QI_256_DESC QiDesc;
if (VTdUnitInfo->EnableQueuedInvalidation == 0) {
//
@@ -304,8 +371,10 @@ InvalidateContextCache (
//
// Queued Invalidation
//
- QiDesc.Low = QI_CC_FM(0) | QI_CC_SID(0) | QI_CC_DID(0) | QI_CC_GRAN(1) | QI_CC_TYPE;
- QiDesc.High = 0;
+ QiDesc.Uint64[0] = QI_CC_FM(0) | QI_CC_SID(0) | QI_CC_DID(0) | QI_CC_GRAN(1) | QI_CC_TYPE;
+ QiDesc.Uint64[1] = 0;
+ QiDesc.Uint64[2] = 0;
+ QiDesc.Uint64[3] = 0;
return SubmitQueuedInvalidationDescriptor(VTdUnitInfo, &QiDesc);
}
@@ -326,7 +395,7 @@ InvalidateIOTLB (
UINT64 Reg64;
VTD_ECAP_REG ECapReg;
VTD_CAP_REG CapReg;
- QI_DESC QiDesc;
+ QI_256_DESC QiDesc;
if (VTdUnitInfo->EnableQueuedInvalidation == 0) {
//
@@ -352,8 +421,10 @@ InvalidateIOTLB (
// Queued Invalidation
//
CapReg.Uint64 = MmioRead64 (VTdUnitInfo->VtdUnitBaseAddress + R_CAP_REG);
- QiDesc.Low = QI_IOTLB_DID(0) | QI_IOTLB_DR(CAP_READ_DRAIN(CapReg.Uint64)) | QI_IOTLB_DW(CAP_WRITE_DRAIN(CapReg.Uint64)) | QI_IOTLB_GRAN(1) | QI_IOTLB_TYPE;
- QiDesc.High = QI_IOTLB_ADDR(0) | QI_IOTLB_IH(0) | QI_IOTLB_AM(0);
+ QiDesc.Uint64[0] = QI_IOTLB_DID(0) | QI_IOTLB_DR(CAP_READ_DRAIN(CapReg.Uint64)) | QI_IOTLB_DW(CAP_WRITE_DRAIN(CapReg.Uint64)) | QI_IOTLB_GRAN(1) | QI_IOTLB_TYPE;
+ QiDesc.Uint64[1] = QI_IOTLB_ADDR(0) | QI_IOTLB_IH(0) | QI_IOTLB_AM(0);
+ QiDesc.Uint64[2] = 0;
+ QiDesc.Uint64[3] = 0;
return SubmitQueuedInvalidationDescriptor(VTdUnitInfo, &QiDesc);
}
@@ -390,6 +461,7 @@ ClearGlobalCommandRegisterBits (
do {
Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
} while ((Reg32 & BitMask) == BitMask);
+ DEBUG ((DEBUG_INFO, "GSTS_REG : 0x%08x \n", Reg32));
}
/**
@@ -421,6 +493,7 @@ SetGlobalCommandRegisterBits (
do {
Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
} while ((Reg32 & BitMask) == 0);
+ DEBUG ((DEBUG_INFO, "GSTS_REG : 0x%08x \n", Reg32));
}
/**
@@ -451,11 +524,6 @@ EnableDmarPreMem (
Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
DEBUG ((DEBUG_INFO, "EnableDmarPreMem: R_GSTS_REG = 0x%x \n", Reg32));
- //
- // Init DMAr Fault Event and Data registers
- //
- Reg32 = MmioRead32 (VtdUnitBaseAddress + R_FEDATA_REG);
-
//
// Write Buffer Flush
//
@@ -513,6 +581,9 @@ EnableDmar (
//
MmioWrite64 (VtdUnitBaseAddress + R_RTADDR_REG, (UINT64) (RootEntryTable | V_RTADDR_REG_TTM_ADM));
+ DEBUG ((DEBUG_INFO, "EnableDmar: waiting for RTPS bit to be set... \n"));
+ SetGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_REG_SRTP);
+
DEBUG((DEBUG_INFO, "Enable Abort DMA Mode...\n"));
SetGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_REG_TE);
@@ -520,16 +591,10 @@ EnableDmar (
DEBUG ((DEBUG_INFO, "RootEntryTable 0x%x \n", RootEntryTable));
MmioWrite64 (VtdUnitBaseAddress + R_RTADDR_REG, (UINT64) RootEntryTable);
+ DEBUG ((DEBUG_INFO, "EnableDmar: waiting for RTPS bit to be set... \n"));
+ SetGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_REG_SRTP);
}
- DEBUG ((DEBUG_INFO, "EnableDmar: waiting for RTPS bit to be set... \n"));
- SetGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_REG_SRTP);
-
- //
- // Init DMAr Fault Event and Data registers
- //
- MmioRead32 (VtdUnitBaseAddress + R_FEDATA_REG);
-
//
// Write Buffer Flush before invalidation
//
@@ -552,6 +617,9 @@ EnableDmar (
DEBUG ((DEBUG_INFO, "RootEntryTable 0x%x \n", RootEntryTable));
MmioWrite64 (VtdUnitBaseAddress + R_RTADDR_REG, (UINT64) RootEntryTable);
+
+ DEBUG ((DEBUG_INFO, "EnableDmar: waiting for RTPS bit to be set... \n"));
+ SetGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_REG_SRTP);
}
//
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmarPei.h b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmarPei.h
index 5ade9ec35..4d4b912f2 100644
--- a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmarPei.h
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmarPei.h
@@ -21,9 +21,8 @@ typedef struct {
VTD_ECAP_REG ECapReg;
BOOLEAN Is5LevelPaging;
UINT8 EnableQueuedInvalidation;
- UINT16 QiDescLength;
- QI_DESC *QiDesc;
- UINT16 QiFreeHead;
+ VOID *QiDescBuffer;
+ UINTN QiDescBufferSize;
UINTN FixedSecondLevelPagingEntry;
UINTN RootEntryTable;
UINTN ExtRootEntryTable;
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.c
index 628565ee7..878c952b7 100644
--- a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.c
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.c
@@ -496,6 +496,9 @@ SetupVtd (
if (EFI_ERROR (Status)) {
return;
}
+
+ DumpVtdIfError ();
+
DEBUG ((DEBUG_INFO, "PrepareVtdConfig\n"));
PrepareVtdConfig ();
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.h b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.h
index 7dd29a243..e83ebff41 100644
--- a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.h
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.h
@@ -81,9 +81,8 @@ typedef struct {
PCI_DEVICE_INFORMATION PciDeviceInfo;
BOOLEAN Is5LevelPaging;
UINT8 EnableQueuedInvalidation;
- UINT16 QiDescLength;
- QI_DESC *QiDesc;
- UINT16 QiFreeHead;
+ VOID *QiDescBuffer;
+ UINTN QiDescBufferSize;
} VTD_UNIT_INFORMATION;
//
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/VtdReg.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/VtdReg.c
index 8e834f4c4..be54cf99d 100644
--- a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/VtdReg.c
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/VtdReg.c
@@ -68,71 +68,89 @@ PerpareCacheInvalidationInterface (
IN UINTN VtdIndex
)
{
- UINT16 QueueSize;
- UINT64 Reg64;
- UINT32 Reg32;
-
- if (mVtdUnitInformation[VtdIndex].VerReg.Bits.Major <= 5) {
- mVtdUnitInformation[VtdIndex].EnableQueuedInvalidation = 0;
+ UINT8 DescriptorWidth;
+ UINTN QueueSize;
+ UINT32 Reg32;
+ VTD_IQA_REG IqaReg;
+ VTD_UNIT_INFORMATION *VTdUnitInfo;
+ UINTN VtdUnitBaseAddress;
+
+ VTdUnitInfo = &mVtdUnitInformation[VtdIndex];
+ VtdUnitBaseAddress = VTdUnitInfo->VtdUnitBaseAddress;
+
+ if (VTdUnitInfo->VerReg.Bits.Major <= 5) {
+ VTdUnitInfo->EnableQueuedInvalidation = 0;
DEBUG ((DEBUG_INFO, "Use Register-based Invalidation Interface for engine [%d]\n", VtdIndex));
return EFI_SUCCESS;
}
- if (mVtdUnitInformation[VtdIndex].ECapReg.Bits.QI == 0) {
+ if (VTdUnitInfo->ECapReg.Bits.QI == 0) {
DEBUG ((DEBUG_ERROR, "Hardware does not support queued invalidations interface for engine [%d]\n", VtdIndex));
return EFI_UNSUPPORTED;
}
- mVtdUnitInformation[VtdIndex].EnableQueuedInvalidation = 1;
+ VTdUnitInfo->EnableQueuedInvalidation = 1;
DEBUG ((DEBUG_INFO, "Use Queued Invalidation Interface for engine [%d]\n", VtdIndex));
- Reg32 = MmioRead32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_GSTS_REG);
+ Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
if ((Reg32 & B_GSTS_REG_QIES) != 0) {
DEBUG ((DEBUG_ERROR,"Queued Invalidation Interface was enabled.\n"));
Reg32 &= (~B_GSTS_REG_QIES);
- MmioWrite32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_GCMD_REG, Reg32);
+ MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, Reg32);
do {
- Reg32 = MmioRead32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_GSTS_REG);
+ Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
} while ((Reg32 & B_GSTS_REG_QIES) != 0);
}
//
// Initialize the Invalidation Queue Tail Register to zero.
//
- MmioWrite64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_IQT_REG, 0);
+ MmioWrite64 (VtdUnitBaseAddress + R_IQT_REG, 0);
//
// Setup the IQ address, size and descriptor width through the Invalidation Queue Address Register
//
- QueueSize = 0;
- mVtdUnitInformation[VtdIndex].QiDescLength = 1 << (QueueSize + 8);
- mVtdUnitInformation[VtdIndex].QiDesc = (QI_DESC *) AllocatePages (EFI_SIZE_TO_PAGES(sizeof(QI_DESC) * mVtdUnitInformation[VtdIndex].QiDescLength));
-
- if (mVtdUnitInformation[VtdIndex].QiDesc == NULL) {
- mVtdUnitInformation[VtdIndex].QiDescLength = 0;
- DEBUG ((DEBUG_ERROR,"Could not Alloc Invalidation Queue Buffer.\n"));
- return EFI_OUT_OF_RESOURCES;
+ if (VTdUnitInfo->QiDescBuffer == NULL) {
+ //
+ // It uses 256-bit descriptor
+ // Queue size is 128.
+ //
+ DescriptorWidth = 1;
+ QueueSize = 0;
+
+ VTdUnitInfo->QiDescBufferSize = (sizeof (QI_256_DESC) * ((UINTN) 1 << (QueueSize + 7)));
+ VTdUnitInfo->QiDescBuffer = AllocatePages (EFI_SIZE_TO_PAGES (VTdUnitInfo->QiDescBufferSize));
+ if (VTdUnitInfo->QiDescBuffer == NULL) {
+ DEBUG ((DEBUG_ERROR,"Could not Alloc Invalidation Queue Buffer.\n"));
+ return EFI_OUT_OF_RESOURCES;
+ }
}
- DEBUG ((DEBUG_INFO, "Invalidation Queue Length : %d\n", mVtdUnitInformation[VtdIndex].QiDescLength));
- Reg64 = (UINT64)(UINTN)mVtdUnitInformation[VtdIndex].QiDesc;
- Reg64 |= QueueSize;
- MmioWrite64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_IQA_REG, Reg64);
+ DEBUG ((DEBUG_INFO, "Invalidation Queue Buffer Size : %d\n", VTdUnitInfo->QiDescBufferSize));
+ //
+ // 4KB Aligned address
+ //
+ IqaReg.Uint64 = (UINT64) (UINTN) VTdUnitInfo->QiDescBuffer;
+ IqaReg.Bits.DW = DescriptorWidth;
+ IqaReg.Bits.QS = QueueSize;
+ MmioWrite64 (VtdUnitBaseAddress + R_IQA_REG, IqaReg.Uint64);
+ IqaReg.Uint64 = MmioRead64 (VtdUnitBaseAddress + R_IQA_REG);
+ DEBUG ((DEBUG_INFO, "IQA_REG [0x%lx]\n", IqaReg.Uint64));
+
+ DEBUG ((DEBUG_INFO, "IQH_REG [0x%lx]\n", MmioRead64 (VtdUnitBaseAddress + R_IQH_REG)));
//
// Enable the queued invalidation interface through the Global Command Register.
// When enabled, hardware sets the QIES field in the Global Status Register.
//
- Reg32 = MmioRead32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_GSTS_REG);
+ Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
Reg32 |= B_GMCD_REG_QIE;
- MmioWrite32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_GCMD_REG, Reg32);
+ MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, Reg32);
DEBUG ((DEBUG_INFO, "Enable Queued Invalidation Interface. GCMD_REG = 0x%x\n", Reg32));
do {
- Reg32 = MmioRead32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_GSTS_REG);
+ Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
} while ((Reg32 & B_GSTS_REG_QIES) == 0);
- mVtdUnitInformation[VtdIndex].QiFreeHead = 0;
-
return EFI_SUCCESS;
}
@@ -146,21 +164,24 @@ DisableQueuedInvalidationInterface (
IN UINTN VtdIndex
)
{
- UINT32 Reg32;
+ UINT32 Reg32;
+ VTD_UNIT_INFORMATION *VTdUnitInfo;
- if (mVtdUnitInformation[VtdIndex].EnableQueuedInvalidation != 0) {
- Reg32 = MmioRead32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_GSTS_REG);
+ VTdUnitInfo = &mVtdUnitInformation[VtdIndex];
+
+ if (VTdUnitInfo->EnableQueuedInvalidation != 0) {
+ Reg32 = MmioRead32 (VTdUnitInfo->VtdUnitBaseAddress + R_GSTS_REG);
Reg32 &= (~B_GMCD_REG_QIE);
- MmioWrite32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_GCMD_REG, Reg32);
+ MmioWrite32 (VTdUnitInfo->VtdUnitBaseAddress + R_GCMD_REG, Reg32);
DEBUG ((DEBUG_INFO, "Disable Queued Invalidation Interface. GCMD_REG = 0x%x\n", Reg32));
do {
- Reg32 = MmioRead32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_GSTS_REG);
+ Reg32 = MmioRead32 (VTdUnitInfo->VtdUnitBaseAddress + R_GSTS_REG);
} while ((Reg32 & B_GSTS_REG_QIES) != 0);
- if (mVtdUnitInformation[VtdIndex].QiDesc != NULL) {
- FreePages(mVtdUnitInformation[VtdIndex].QiDesc, EFI_SIZE_TO_PAGES(sizeof(QI_DESC) * mVtdUnitInformation[VtdIndex].QiDescLength));
- mVtdUnitInformation[VtdIndex].QiDesc = NULL;
- mVtdUnitInformation[VtdIndex].QiDescLength = 0;
+ if (VTdUnitInfo->QiDescBuffer != NULL) {
+ FreePages(VTdUnitInfo->QiDescBuffer, EFI_SIZE_TO_PAGES (VTdUnitInfo->QiDescBufferSize));
+ VTdUnitInfo->QiDescBuffer = NULL;
+ VTdUnitInfo->QiDescBufferSize = 0;
}
mVtdUnitInformation[VtdIndex].EnableQueuedInvalidation = 0;
@@ -180,27 +201,16 @@ QueuedInvalidationCheckFault (
IN UINTN VtdIndex
)
{
- UINT32 FaultReg;
+ UINT32 FaultReg;
+ VTD_IQERCD_REG IqercdReg;
FaultReg = MmioRead32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_FSTS_REG);
- if (FaultReg & B_FSTS_REG_IQE) {
- DEBUG((DEBUG_ERROR, "Detect Invalidation Queue Error [0x%08x]\n", FaultReg));
- FaultReg |= B_FSTS_REG_IQE;
- MmioWrite32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_FSTS_REG, FaultReg);
- return RETURN_DEVICE_ERROR;
- }
+ if (FaultReg & (B_FSTS_REG_IQE | B_FSTS_REG_ITE | B_FSTS_REG_ICE)) {
+ IqercdReg.Uint64 = MmioRead64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_IQERCD_REG);
- if (FaultReg & B_FSTS_REG_ITE) {
- DEBUG((DEBUG_ERROR, "Detect Invalidation Time-out Error [0x%08x]\n", FaultReg));
- FaultReg |= B_FSTS_REG_ITE;
- MmioWrite32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_FSTS_REG, FaultReg);
- return RETURN_DEVICE_ERROR;
- }
+ DEBUG((DEBUG_ERROR, "Detect Queue Invalidation Error [0x%08x] - IQERCD [0x%016lx]\n", FaultReg, IqercdReg.Uint64));
- if (FaultReg & B_FSTS_REG_ICE) {
- DEBUG((DEBUG_ERROR, "Detect Invalidation Completion Error [0x%08x]\n", FaultReg));
- FaultReg |= B_FSTS_REG_ICE;
MmioWrite32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_FSTS_REG, FaultReg);
return RETURN_DEVICE_ERROR;
}
@@ -221,36 +231,83 @@ QueuedInvalidationCheckFault (
**/
EFI_STATUS
SubmitQueuedInvalidationDescriptor (
- IN UINTN VtdIndex,
- IN QI_DESC *Desc
+ IN UINTN VtdIndex,
+ IN QI_256_DESC *Desc
)
{
- EFI_STATUS Status;
- UINT16 QiDescLength;
- QI_DESC *BaseDesc;
- UINT64 Reg64Iqt;
- UINT64 Reg64Iqh;
+ EFI_STATUS Status;
+ UINTN VtdUnitBaseAddress;
+ UINTN QueueSize;
+ UINTN QueueTail;
+ UINTN QueueHead;
+ QI_DESC *Qi128Desc;
+ QI_256_DESC *Qi256Desc;
+ VTD_IQA_REG IqaReg;
+ VTD_IQT_REG IqtReg;
+ VTD_IQH_REG IqhReg;
if (Desc == NULL) {
return EFI_INVALID_PARAMETER;
}
- QiDescLength = mVtdUnitInformation[VtdIndex].QiDescLength;
- BaseDesc = mVtdUnitInformation[VtdIndex].QiDesc;
-
- DEBUG((DEBUG_VERBOSE, "[%d] Submit QI Descriptor [0x%08x, 0x%08x] Free Head (%d)\n", VtdIndex, Desc->Low, Desc->High, mVtdUnitInformation[VtdIndex].QiFreeHead));
-
- BaseDesc[mVtdUnitInformation[VtdIndex].QiFreeHead].Low = Desc->Low;
- BaseDesc[mVtdUnitInformation[VtdIndex].QiFreeHead].High = Desc->High;
- FlushPageTableMemory(VtdIndex, (UINTN) &BaseDesc[mVtdUnitInformation[VtdIndex].QiFreeHead], sizeof(QI_DESC));
+ VtdUnitBaseAddress = mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress;
+ IqaReg.Uint64 = MmioRead64 (VtdUnitBaseAddress + R_IQA_REG);
+ if (IqaReg.Bits.IQA == 0) {
+ DEBUG ((DEBUG_ERROR,"Invalidation Queue Buffer not ready [0x%lx]\n", IqaReg.Uint64));
+ return EFI_NOT_READY;
+ }
+ IqtReg.Uint64 = MmioRead64 (VtdUnitBaseAddress + R_IQT_REG);
- mVtdUnitInformation[VtdIndex].QiFreeHead = (mVtdUnitInformation[VtdIndex].QiFreeHead + 1) % QiDescLength;
+ if (IqaReg.Bits.DW == 0) {
+ //
+ // 128-bit descriptor
+ //
+ QueueSize = (UINTN) (1 << (IqaReg.Bits.QS + 8));
+ Qi128Desc = (QI_DESC *) (UINTN) (IqaReg.Bits.IQA << VTD_PAGE_SHIFT);
+ QueueTail = (UINTN) IqtReg.Bits128Desc.QT;
+ Qi128Desc += QueueTail;
+ Qi128Desc->Low = Desc->Uint64[0];
+ Qi128Desc->High = Desc->Uint64[1];
+ FlushPageTableMemory (VtdIndex, (UINTN) Qi128Desc, sizeof(QI_DESC));
+ QueueTail = (QueueTail + 1) % QueueSize;
+
+ DEBUG ((DEBUG_VERBOSE, "[0x%x] Submit QI Descriptor 0x%x [0x%016lx, 0x%016lx]\n",
+ VtdUnitBaseAddress,
+ QueueTail,
+ Desc->Uint64[0],
+ Desc->Uint64[1]));
+
+ IqtReg.Bits128Desc.QT = QueueTail;
+ } else {
+ //
+ // 256-bit descriptor
+ //
+ QueueSize = (UINTN) (1 << (IqaReg.Bits.QS + 7));
+ Qi256Desc = (QI_256_DESC *) (UINTN) (IqaReg.Bits.IQA << VTD_PAGE_SHIFT);
+ QueueTail = (UINTN) IqtReg.Bits256Desc.QT;
+ Qi256Desc += QueueTail;
+ Qi256Desc->Uint64[0] = Desc->Uint64[0];
+ Qi256Desc->Uint64[1] = Desc->Uint64[1];
+ Qi256Desc->Uint64[2] = Desc->Uint64[2];
+ Qi256Desc->Uint64[3] = Desc->Uint64[3];
+ FlushPageTableMemory (VtdIndex, (UINTN) Qi256Desc, sizeof(QI_256_DESC));
+ QueueTail = (QueueTail + 1) % QueueSize;
+
+ DEBUG ((DEBUG_VERBOSE, "[0x%x] Submit QI Descriptor 0x%x [0x%016lx, 0x%016lx, 0x%016lx, 0x%016lx]\n",
+ VtdUnitBaseAddress,
+ QueueTail,
+ Desc->Uint64[0],
+ Desc->Uint64[1],
+ Desc->Uint64[2],
+ Desc->Uint64[3]));
+
+ IqtReg.Bits256Desc.QT = QueueTail;
+ }
//
// Update the HW tail register indicating the presence of new descriptors.
//
- Reg64Iqt = mVtdUnitInformation[VtdIndex].QiFreeHead << DMAR_IQ_SHIFT;
- MmioWrite64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_IQT_REG, Reg64Iqt);
+ MmioWrite64 (VtdUnitBaseAddress + R_IQT_REG, IqtReg.Uint64);
Status = EFI_SUCCESS;
do {
@@ -260,8 +317,13 @@ SubmitQueuedInvalidationDescriptor (
break;
}
- Reg64Iqh = MmioRead64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_IQH_REG);
- } while (Reg64Iqt != Reg64Iqh);
+ IqhReg.Uint64 = MmioRead64 (VtdUnitBaseAddress + R_IQH_REG);
+ if (IqaReg.Bits.DW == 0) {
+ QueueHead = (UINTN) IqhReg.Bits128Desc.QH;
+ } else {
+ QueueHead = (UINTN) IqhReg.Bits256Desc.QH;
+ }
+ } while (QueueTail != QueueHead);
return Status;
}
@@ -276,8 +338,8 @@ InvalidateContextCache (
IN UINTN VtdIndex
)
{
- UINT64 Reg64;
- QI_DESC QiDesc;
+ UINT64 Reg64;
+ QI_256_DESC QiDesc;
if (mVtdUnitInformation[VtdIndex].EnableQueuedInvalidation == 0) {
//
@@ -300,8 +362,10 @@ InvalidateContextCache (
//
// Queued Invalidation
//
- QiDesc.Low = QI_CC_FM(0) | QI_CC_SID(0) | QI_CC_DID(0) | QI_CC_GRAN(1) | QI_CC_TYPE;
- QiDesc.High = 0;
+ QiDesc.Uint64[0] = QI_CC_FM(0) | QI_CC_SID(0) | QI_CC_DID(0) | QI_CC_GRAN(1) | QI_CC_TYPE;
+ QiDesc.Uint64[1] = 0;
+ QiDesc.Uint64[2] = 0;
+ QiDesc.Uint64[3] = 0;
return SubmitQueuedInvalidationDescriptor(VtdIndex, &QiDesc);
}
@@ -318,8 +382,8 @@ InvalidateIOTLB (
IN UINTN VtdIndex
)
{
- UINT64 Reg64;
- QI_DESC QiDesc;
+ UINT64 Reg64;
+ QI_256_DESC QiDesc;
if (mVtdUnitInformation[VtdIndex].EnableQueuedInvalidation == 0) {
//
@@ -342,8 +406,10 @@ InvalidateIOTLB (
//
// Queued Invalidation
//
- QiDesc.Low = QI_IOTLB_DID(0) | QI_IOTLB_DR(CAP_READ_DRAIN(mVtdUnitInformation[VtdIndex].CapReg.Uint64)) | QI_IOTLB_DW(CAP_WRITE_DRAIN(mVtdUnitInformation[VtdIndex].CapReg.Uint64)) | QI_IOTLB_GRAN(1) | QI_IOTLB_TYPE;
- QiDesc.High = QI_IOTLB_ADDR(0) | QI_IOTLB_IH(0) | QI_IOTLB_AM(0);
+ QiDesc.Uint64[0] = QI_IOTLB_DID(0) | QI_IOTLB_DR(CAP_READ_DRAIN(mVtdUnitInformation[VtdIndex].CapReg.Uint64)) | QI_IOTLB_DW(CAP_WRITE_DRAIN(mVtdUnitInformation[VtdIndex].CapReg.Uint64)) | QI_IOTLB_GRAN(1) | QI_IOTLB_TYPE;
+ QiDesc.Uint64[1] = QI_IOTLB_ADDR(0) | QI_IOTLB_IH(0) | QI_IOTLB_AM(0);
+ QiDesc.Uint64[2] = 0;
+ QiDesc.Uint64[3] = 0;
return SubmitQueuedInvalidationDescriptor(VtdIndex, &QiDesc);
}
@@ -504,6 +570,7 @@ ClearGlobalCommandRegisterBits (
do {
Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
} while ((Reg32 & BitMask) == BitMask);
+ DEBUG ((DEBUG_INFO, "GSTS_REG : 0x%08x \n", Reg32));
}
/**
@@ -535,6 +602,7 @@ SetGlobalCommandRegisterBits (
do {
Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
} while ((Reg32 & BitMask) == 0);
+ DEBUG ((DEBUG_INFO, "GSTS_REG : 0x%08x \n", Reg32));
}
/**
@@ -600,22 +668,19 @@ EnableDmar (
//
UpdateRootTableAddressRegister (Index, TRUE);
+ DEBUG((DEBUG_INFO, "EnableDmar: waiting for RTPS bit to be set... \n"));
+ SetGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_REG_SRTP);
+
DEBUG((DEBUG_INFO, "Enable Abort DMA Mode...\n"));
SetGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_REG_TE);
} else {
UpdateRootTableAddressRegister (Index, FALSE);
+ DEBUG((DEBUG_INFO, "EnableDmar: waiting for RTPS bit to be set... \n"));
+ SetGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_REG_SRTP);
}
- DEBUG((DEBUG_INFO, "EnableDmar: waiting for RTPS bit to be set... \n"));
- SetGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_REG_SRTP);
-
- //
- // Init DMAr Fault Event and Data registers
- //
- MmioRead32 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_FEDATA_REG);
-
//
// Write Buffer Flush before invalidation
//
@@ -637,6 +702,9 @@ EnableDmar (
}
UpdateRootTableAddressRegister (Index, FALSE);
+
+ DEBUG((DEBUG_INFO, "EnableDmar: waiting for RTPS bit to be set... \n"));
+ SetGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_REG_SRTP);
}
//
diff --git a/Silicon/Intel/IntelSiliconPkg/Include/IndustryStandard/Vtd.h b/Silicon/Intel/IntelSiliconPkg/Include/IndustryStandard/Vtd.h
index 32fbdd02e..3e1b8c3c5 100644
--- a/Silicon/Intel/IntelSiliconPkg/Include/IndustryStandard/Vtd.h
+++ b/Silicon/Intel/IntelSiliconPkg/Include/IndustryStandard/Vtd.h
@@ -259,6 +259,8 @@ typedef union {
#define R_IQA_REG 0x90
+#define R_IQERCD_REG 0xB0
+
#define VTD_PAGE_SHIFT (12)
#define VTD_PAGE_SIZE (1UL << VTD_PAGE_SHIFT)
#define VTD_PAGE_MASK (((UINT64)-1) << VTD_PAGE_SHIFT)
@@ -289,13 +291,20 @@ typedef union {
#define QI_IWD_STATUS_WRITE (((UINT64)1) << 5)
//
-// This is the queued invalidate descriptor.
+// queued invalidation 128-bit descriptor
//
typedef struct {
- UINT64 Low;
- UINT64 High;
+ UINT64 Low;
+ UINT64 High;
} QI_DESC;
+//
+// queued invalidation 256-bit descriptor
+//
+typedef struct {
+ UINT64 Uint64[4];
+} QI_256_DESC;
+
typedef union {
struct {
UINT8 Minor:4;
@@ -411,6 +420,56 @@ typedef union {
UINT64 Uint64[2];
} VTD_FRCD_REG;
+typedef union {
+ struct {
+ UINT32 IQEI:4; // Invalidation Queue Error Info
+ UINT32 Rsvd_4:28;
+ UINT32 ITESID:16; // Invalidation Time-out Error Source Identifier
+ UINT32 ICESID:16; // Invalidation Completion Error Source Identifier
+ } Bits;
+ UINT64 Uint64;
+} VTD_IQERCD_REG;
+
+typedef union {
+ struct {
+ UINT64 Rsvd_0:4;
+ UINT64 QH:15; // Queue Head
+ UINT64 Rsvd_19:45;
+ } Bits128Desc;
+ struct {
+ UINT64 Rsvd_0:4;
+ UINT64 Rsvd_4:1;
+ UINT64 QH:14; // Queue Head
+ UINT64 Rsvd_19:45;
+ } Bits256Desc;
+ UINT64 Uint64;
+} VTD_IQH_REG;
+
+typedef union {
+ struct {
+ UINT64 Rsvd_0:4;
+ UINT64 QT:15; // Queue Tail
+ UINT64 Rsvd_19:45;
+ } Bits128Desc;
+ struct {
+ UINT64 Rsvd_0:4;
+ UINT64 Rsvd_4:1;
+ UINT64 QT:14; // Queue Tail
+ UINT64 Rsvd_19:45;
+ } Bits256Desc;
+ UINT64 Uint64;
+} VTD_IQT_REG;
+
+typedef union {
+ struct {
+ UINT64 QS:3; // Queue Size
+ UINT64 Rsvd_3:8;
+ UINT64 DW:1; // Descriptor Width
+ UINT64 IQA:52; // Invalidation Queue Base Address
+ } Bits;
+ UINT64 Uint64;
+} VTD_IQA_REG;
+
typedef union {
struct {
UINT8 Function:3;
--
2.26.2.windows.1
^ permalink raw reply related [flat|nested] 2+ messages in thread
end of thread, other threads:[~2022-11-30 5:15 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2022-11-30 5:15 [PATCH] IntelSiliconPkg/VTd: Use 256-bit invaildation queue descriptor Sheng Wei
-- strict thread matches above, loose matches on Subject: below --
2022-11-21 5:43 Sheng Wei
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox