* [PATCH v3] IntelSiliconPkg/VTd: Add iommu 5 level paging support
@ 2020-11-18 1:17 Sheng Wei
2020-11-18 1:39 ` Yao, Jiewen
0 siblings, 1 reply; 6+ messages in thread
From: Sheng Wei @ 2020-11-18 1:17 UTC (permalink / raw)
To: devel; +Cc: Ray Ni, Rangasai V Chaganty, Jiewen Yao, Jenny Huang
Support iommu 5 level paging for translation table.
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3067
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: Jiewen Yao <jiewen.yao@intel.com>
Cc: Jenny Huang <jenny.huang@intel.com>
---
.../Feature/VTd/IntelVTdDxe/DmaProtection.c | 4 +-
.../Feature/VTd/IntelVTdDxe/DmaProtection.h | 19 +-
.../Feature/VTd/IntelVTdDxe/TranslationTable.c | 287 +++++++++++++++------
.../Feature/VTd/IntelVTdDxe/TranslationTableEx.c | 35 ++-
.../Feature/VTd/IntelVTdDxe/VtdReg.c | 10 +-
Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dec | 3 +
6 files changed, 258 insertions(+), 100 deletions(-)
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.c
index 9b6135ef..628565ee 100644
--- a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.c
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.c
@@ -523,10 +523,10 @@ SetupVtd (
for (Index = 0; Index < mVtdUnitNumber; Index++) {
DEBUG ((DEBUG_INFO,"VTD Unit %d (Segment: %04x)\n", Index, mVtdUnitInformation[Index].Segment));
if (mVtdUnitInformation[Index].ExtRootEntryTable != NULL) {
- DumpDmarExtContextEntryTable (mVtdUnitInformation[Index].ExtRootEntryTable);
+ DumpDmarExtContextEntryTable (mVtdUnitInformation[Index].ExtRootEntryTable, mVtdUnitInformation[Index].Is5LevelPaging);
}
if (mVtdUnitInformation[Index].RootEntryTable != NULL) {
- DumpDmarContextEntryTable (mVtdUnitInformation[Index].RootEntryTable);
+ DumpDmarContextEntryTable (mVtdUnitInformation[Index].RootEntryTable, mVtdUnitInformation[Index].Is5LevelPaging);
}
}
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.h b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.h
index a3331db8..f641cea0 100644
--- a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.h
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.h
@@ -77,6 +77,7 @@ typedef struct {
BOOLEAN HasDirtyContext;
BOOLEAN HasDirtyPages;
PCI_DEVICE_INFORMATION PciDeviceInfo;
+ BOOLEAN Is5LevelPaging;
} VTD_UNIT_INFORMATION;
//
@@ -375,31 +376,37 @@ ParseDmarAcpiTableRmrr (
/**
Dump DMAR context entry table.
- @param[in] RootEntry DMAR root entry.
+ @param[in] RootEntry DMAR root entry.
+ @param[in] Is5LevelPaging If it is the 5 level paging.
**/
VOID
DumpDmarContextEntryTable (
- IN VTD_ROOT_ENTRY *RootEntry
+ IN VTD_ROOT_ENTRY *RootEntry,
+ IN BOOLEAN Is5LevelPaging
);
/**
Dump DMAR extended context entry table.
- @param[in] ExtRootEntry DMAR extended root entry.
+ @param[in] ExtRootEntry DMAR extended root entry.
+ @param[in] Is5LevelPaging If it is the 5 level paging.
**/
VOID
DumpDmarExtContextEntryTable (
- IN VTD_EXT_ROOT_ENTRY *ExtRootEntry
+ IN VTD_EXT_ROOT_ENTRY *ExtRootEntry,
+ IN BOOLEAN Is5LevelPaging
);
/**
Dump DMAR second level paging entry.
- @param[in] SecondLevelPagingEntry The second level paging entry.
+ @param[in] SecondLevelPagingEntry The second level paging entry.
+ @param[in] Is5LevelPaging If it is the 5 level paging.
**/
VOID
DumpSecondLevelPagingEntry (
- IN VOID *SecondLevelPagingEntry
+ IN VOID *SecondLevelPagingEntry,
+ IN BOOLEAN Is5LevelPaging
);
/**
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTable.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTable.c
index 201d663d..cb59860a 100644
--- a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTable.c
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTable.c
@@ -128,11 +128,32 @@ CreateContextEntry (
DEBUG ((DEBUG_INFO,"Source: S%04x B%02x D%02x F%02x\n", mVtdUnitInformation[VtdIndex].Segment, SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.Function));
- if ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW & BIT2) == 0) {
- DEBUG((DEBUG_ERROR, "!!!! 4-level page-table is not supported on VTD %d !!!!\n", VtdIndex));
+ mVtdUnitInformation[VtdIndex].Is5LevelPaging = FALSE;
+ if ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW & BIT3) != 0) {
+ if ((PcdGet8(PcdVTdPolicyPropertyMask) & BIT3) != 0) {
+ DEBUG((DEBUG_ERROR, "Force to use 4-level page-table on VTD %d\n", VtdIndex));
+ ContextEntry->Bits.AddressWidth = 0x2;
+ } if ((PcdGet8(PcdVTdPolicyPropertyMask) & BIT4) != 0) {
+ DEBUG((DEBUG_ERROR, "Force to use 5-level page-table on VTD %d\n", VtdIndex));
+ ContextEntry->Bits.AddressWidth = 0x3;
+ mVtdUnitInformation[VtdIndex].Is5LevelPaging = TRUE;
+ } else {
+ if (mAcpiDmarTable->HostAddressWidth > 48) {
+ DEBUG((DEBUG_ERROR, "Using 5-level page-table on VTD %d\n", VtdIndex));
+ ContextEntry->Bits.AddressWidth = 0x3;
+ mVtdUnitInformation[VtdIndex].Is5LevelPaging = TRUE;
+ } else {
+ DEBUG((DEBUG_ERROR, "Using 4-level page-table on VTD %d\n", VtdIndex));
+ ContextEntry->Bits.AddressWidth = 0x2;
+ }
+ }
+ } else if ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW & BIT2) != 0) {
+ DEBUG((DEBUG_ERROR, "Using 4-level page-table on VTD %d\n", VtdIndex));
+ ContextEntry->Bits.AddressWidth = 0x2;
+ } else {
+ DEBUG((DEBUG_ERROR, "!!!! Page-table type is not supported on VTD %d !!!!\n", VtdIndex));
return EFI_UNSUPPORTED;
}
- ContextEntry->Bits.AddressWidth = 0x2;
}
FlushPageTableMemory (VtdIndex, (UINTN)mVtdUnitInformation[VtdIndex].RootEntryTable, EFI_PAGES_TO_SIZE(EntryTablePages));
@@ -148,6 +169,7 @@ CreateContextEntry (
@param[in] MemoryBase The base of the memory.
@param[in] MemoryLimit The limit of the memory.
@param[in] IoMmuAccess The IOMMU access.
+ @param[in] Is5LevelPaging If it is the 5 level paging.
@return The second level paging entry.
**/
@@ -157,16 +179,23 @@ CreateSecondLevelPagingEntryTable (
IN VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry,
IN UINT64 MemoryBase,
IN UINT64 MemoryLimit,
- IN UINT64 IoMmuAccess
+ IN UINT64 IoMmuAccess,
+ IN BOOLEAN Is5LevelPaging
)
{
+ UINTN Index5;
UINTN Index4;
UINTN Index3;
UINTN Index2;
+ UINTN Lvl5Start;
+ UINTN Lvl5End;
+ UINTN Lvl4PagesStart;
+ UINTN Lvl4PagesEnd;
UINTN Lvl4Start;
UINTN Lvl4End;
UINTN Lvl3Start;
UINTN Lvl3End;
+ VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl5PtEntry;
VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl4PtEntry;
VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl3PtEntry;
VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl2PtEntry;
@@ -184,7 +213,7 @@ CreateSecondLevelPagingEntryTable (
if (SecondLevelPagingEntry == NULL) {
SecondLevelPagingEntry = AllocateZeroPages (1);
if (SecondLevelPagingEntry == NULL) {
- DEBUG ((DEBUG_ERROR,"Could not Alloc LVL4 PT. \n"));
+ DEBUG ((DEBUG_ERROR,"Could not Alloc LVL4 or LVL5 PT. \n"));
return NULL;
}
FlushPageTableMemory (VtdIndex, (UINTN)SecondLevelPagingEntry, EFI_PAGES_TO_SIZE(1));
@@ -197,66 +226,109 @@ CreateSecondLevelPagingEntryTable (
return SecondLevelPagingEntry;
}
- Lvl4Start = RShiftU64 (BaseAddress, 39) & 0x1FF;
- Lvl4End = RShiftU64 (EndAddress - 1, 39) & 0x1FF;
+ if (Is5LevelPaging) {
+ Lvl5Start = RShiftU64 (BaseAddress, 48) & 0x1FF;
+ Lvl5End = RShiftU64 (EndAddress - 1, 48) & 0x1FF;
+ DEBUG ((DEBUG_INFO," Lvl5Start - 0x%x, Lvl5End - 0x%x\n", Lvl5Start, Lvl5End));
- DEBUG ((DEBUG_INFO," Lvl4Start - 0x%x, Lvl4End - 0x%x\n", Lvl4Start, Lvl4End));
+ Lvl4Start = RShiftU64 (BaseAddress, 39) & 0x1FF;
+ Lvl4End = RShiftU64 (EndAddress - 1, 39) & 0x1FF;
- Lvl4PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY *)SecondLevelPagingEntry;
- for (Index4 = Lvl4Start; Index4 <= Lvl4End; Index4++) {
- if (Lvl4PtEntry[Index4].Uint64 == 0) {
- Lvl4PtEntry[Index4].Uint64 = (UINT64)(UINTN)AllocateZeroPages (1);
- if (Lvl4PtEntry[Index4].Uint64 == 0) {
- DEBUG ((DEBUG_ERROR,"!!!!!! ALLOCATE LVL4 PAGE FAIL (0x%x)!!!!!!\n", Index4));
- ASSERT(FALSE);
- return NULL;
- }
- FlushPageTableMemory (VtdIndex, (UINTN)Lvl4PtEntry[Index4].Uint64, SIZE_4KB);
- SetSecondLevelPagingEntryAttribute (&Lvl4PtEntry[Index4], EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);
- }
+ Lvl4PagesStart = (Lvl5Start<<9) | Lvl4Start;
+ Lvl4PagesEnd = (Lvl5End<<9) | Lvl4End;
+ DEBUG ((DEBUG_INFO," Lvl4PagesStart - 0x%x, Lvl4PagesEnd - 0x%x\n", Lvl4PagesStart, Lvl4PagesEnd));
- Lvl3Start = RShiftU64 (BaseAddress, 30) & 0x1FF;
- if (ALIGN_VALUE_LOW(BaseAddress + SIZE_1GB, SIZE_1GB) <= EndAddress) {
- Lvl3End = SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY) - 1;
- } else {
- Lvl3End = RShiftU64 (EndAddress - 1, 30) & 0x1FF;
+ Lvl5PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY *)SecondLevelPagingEntry;
+ } else {
+ Lvl5Start = RShiftU64 (BaseAddress, 48) & 0x1FF;
+ Lvl5End = Lvl5Start;
+
+ Lvl4Start = RShiftU64 (BaseAddress, 39) & 0x1FF;
+ Lvl4End = RShiftU64 (EndAddress - 1, 39) & 0x1FF;
+ DEBUG ((DEBUG_INFO," Lvl4Start - 0x%x, Lvl4End - 0x%x\n", Lvl4Start, Lvl4End));
+
+ Lvl4PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY *)SecondLevelPagingEntry;
+ }
+
+ for (Index5 = Lvl5Start; Index5 <= Lvl5End; Index5++) {
+ if (Is5LevelPaging) {
+ if (Lvl5PtEntry[Index5].Uint64 == 0) {
+ Lvl5PtEntry[Index5].Uint64 = (UINT64)(UINTN)AllocateZeroPages (1);
+ if (Lvl5PtEntry[Index5].Uint64 == 0) {
+ DEBUG ((DEBUG_ERROR,"!!!!!! ALLOCATE LVL4 PAGE FAIL (0x%x)!!!!!!\n", Index5));
+ ASSERT(FALSE);
+ return NULL;
+ }
+ FlushPageTableMemory (VtdIndex, (UINTN)Lvl5PtEntry[Index5].Uint64, SIZE_4KB);
+ SetSecondLevelPagingEntryAttribute (&Lvl5PtEntry[Index5], EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);
+ }
+ Lvl4Start = Lvl4PagesStart & 0x1FF;
+ if (((Index5+1)<<9) > Lvl4PagesEnd) {
+ Lvl4End = SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY) - 1;;
+ Lvl4PagesStart = (Index5+1)<<9;
+ } else {
+ Lvl4End = Lvl4PagesEnd & 0x1FF;
+ }
+ DEBUG ((DEBUG_INFO," Lvl5(0x%x): Lvl4Start - 0x%x, Lvl4End - 0x%x\n", Index5, Lvl4Start, Lvl4End));
+ Lvl4PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY *)(UINTN)VTD_64BITS_ADDRESS(Lvl5PtEntry[Index5].Bits.AddressLo, Lvl5PtEntry[Index5].Bits.AddressHi);
}
- DEBUG ((DEBUG_INFO," Lvl4(0x%x): Lvl3Start - 0x%x, Lvl3End - 0x%x\n", Index4, Lvl3Start, Lvl3End));
- Lvl3PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY *)(UINTN)VTD_64BITS_ADDRESS(Lvl4PtEntry[Index4].Bits.AddressLo, Lvl4PtEntry[Index4].Bits.AddressHi);
- for (Index3 = Lvl3Start; Index3 <= Lvl3End; Index3++) {
- if (Lvl3PtEntry[Index3].Uint64 == 0) {
- Lvl3PtEntry[Index3].Uint64 = (UINT64)(UINTN)AllocateZeroPages (1);
- if (Lvl3PtEntry[Index3].Uint64 == 0) {
- DEBUG ((DEBUG_ERROR,"!!!!!! ALLOCATE LVL3 PAGE FAIL (0x%x, 0x%x)!!!!!!\n", Index4, Index3));
+ for (Index4 = Lvl4Start; Index4 <= Lvl4End; Index4++) {
+ if (Lvl4PtEntry[Index4].Uint64 == 0) {
+ Lvl4PtEntry[Index4].Uint64 = (UINT64)(UINTN)AllocateZeroPages (1);
+ if (Lvl4PtEntry[Index4].Uint64 == 0) {
+ DEBUG ((DEBUG_ERROR,"!!!!!! ALLOCATE LVL4 PAGE FAIL (0x%x)!!!!!!\n", Index4));
ASSERT(FALSE);
return NULL;
}
- FlushPageTableMemory (VtdIndex, (UINTN)Lvl3PtEntry[Index3].Uint64, SIZE_4KB);
- SetSecondLevelPagingEntryAttribute (&Lvl3PtEntry[Index3], EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);
+ FlushPageTableMemory (VtdIndex, (UINTN)Lvl4PtEntry[Index4].Uint64, SIZE_4KB);
+ SetSecondLevelPagingEntryAttribute (&Lvl4PtEntry[Index4], EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);
}
- Lvl2PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY *)(UINTN)VTD_64BITS_ADDRESS(Lvl3PtEntry[Index3].Bits.AddressLo, Lvl3PtEntry[Index3].Bits.AddressHi);
- for (Index2 = 0; Index2 < SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY); Index2++) {
- Lvl2PtEntry[Index2].Uint64 = BaseAddress;
- SetSecondLevelPagingEntryAttribute (&Lvl2PtEntry[Index2], IoMmuAccess);
- Lvl2PtEntry[Index2].Bits.PageSize = 1;
- BaseAddress += SIZE_2MB;
+ Lvl3Start = RShiftU64 (BaseAddress, 30) & 0x1FF;
+ if (ALIGN_VALUE_LOW(BaseAddress + SIZE_1GB, SIZE_1GB) <= EndAddress) {
+ Lvl3End = SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY) - 1;
+ } else {
+ Lvl3End = RShiftU64 (EndAddress - 1, 30) & 0x1FF;
+ }
+ DEBUG ((DEBUG_INFO," Lvl4(0x%x): Lvl3Start - 0x%x, Lvl3End - 0x%x\n", Index4, Lvl3Start, Lvl3End));
+
+ Lvl3PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY *)(UINTN)VTD_64BITS_ADDRESS(Lvl4PtEntry[Index4].Bits.AddressLo, Lvl4PtEntry[Index4].Bits.AddressHi);
+ for (Index3 = Lvl3Start; Index3 <= Lvl3End; Index3++) {
+ if (Lvl3PtEntry[Index3].Uint64 == 0) {
+ Lvl3PtEntry[Index3].Uint64 = (UINT64)(UINTN)AllocateZeroPages (1);
+ if (Lvl3PtEntry[Index3].Uint64 == 0) {
+ DEBUG ((DEBUG_ERROR,"!!!!!! ALLOCATE LVL3 PAGE FAIL (0x%x, 0x%x)!!!!!!\n", Index4, Index3));
+ ASSERT(FALSE);
+ return NULL;
+ }
+ FlushPageTableMemory (VtdIndex, (UINTN)Lvl3PtEntry[Index3].Uint64, SIZE_4KB);
+ SetSecondLevelPagingEntryAttribute (&Lvl3PtEntry[Index3], EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);
+ }
+
+ Lvl2PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY *)(UINTN)VTD_64BITS_ADDRESS(Lvl3PtEntry[Index3].Bits.AddressLo, Lvl3PtEntry[Index3].Bits.AddressHi);
+ for (Index2 = 0; Index2 < SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY); Index2++) {
+ Lvl2PtEntry[Index2].Uint64 = BaseAddress;
+ SetSecondLevelPagingEntryAttribute (&Lvl2PtEntry[Index2], IoMmuAccess);
+ Lvl2PtEntry[Index2].Bits.PageSize = 1;
+ BaseAddress += SIZE_2MB;
+ if (BaseAddress >= MemoryLimit) {
+ break;
+ }
+ }
+ FlushPageTableMemory (VtdIndex, (UINTN)Lvl2PtEntry, SIZE_4KB);
if (BaseAddress >= MemoryLimit) {
break;
}
}
- FlushPageTableMemory (VtdIndex, (UINTN)Lvl2PtEntry, SIZE_4KB);
+ FlushPageTableMemory (VtdIndex, (UINTN)&Lvl3PtEntry[Lvl3Start], (UINTN)&Lvl3PtEntry[Lvl3End + 1] - (UINTN)&Lvl3PtEntry[Lvl3Start]);
if (BaseAddress >= MemoryLimit) {
break;
}
}
- FlushPageTableMemory (VtdIndex, (UINTN)&Lvl3PtEntry[Lvl3Start], (UINTN)&Lvl3PtEntry[Lvl3End + 1] - (UINTN)&Lvl3PtEntry[Lvl3Start]);
- if (BaseAddress >= MemoryLimit) {
- break;
- }
+ FlushPageTableMemory (VtdIndex, (UINTN)&Lvl4PtEntry[Lvl4Start], (UINTN)&Lvl4PtEntry[Lvl4End + 1] - (UINTN)&Lvl4PtEntry[Lvl4Start]);
}
- FlushPageTableMemory (VtdIndex, (UINTN)&Lvl4PtEntry[Lvl4Start], (UINTN)&Lvl4PtEntry[Lvl4End + 1] - (UINTN)&Lvl4PtEntry[Lvl4Start]);
+ FlushPageTableMemory (VtdIndex, (UINTN)&Lvl5PtEntry[Lvl5Start], (UINTN)&Lvl5PtEntry[Lvl5End + 1] - (UINTN)&Lvl5PtEntry[Lvl5Start]);
return SecondLevelPagingEntry;
}
@@ -266,26 +338,28 @@ CreateSecondLevelPagingEntryTable (
@param[in] VtdIndex The index of the VTd engine.
@param[in] IoMmuAccess The IOMMU access.
+ @param[in] Is5LevelPaging If it is the 5 level paging.
@return The second level paging entry.
**/
VTD_SECOND_LEVEL_PAGING_ENTRY *
CreateSecondLevelPagingEntry (
IN UINTN VtdIndex,
- IN UINT64 IoMmuAccess
+ IN UINT64 IoMmuAccess,
+ IN BOOLEAN Is5LevelPaging
)
{
VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry;
SecondLevelPagingEntry = NULL;
- SecondLevelPagingEntry = CreateSecondLevelPagingEntryTable (VtdIndex, SecondLevelPagingEntry, 0, mBelow4GMemoryLimit, IoMmuAccess);
+ SecondLevelPagingEntry = CreateSecondLevelPagingEntryTable (VtdIndex, SecondLevelPagingEntry, 0, mBelow4GMemoryLimit, IoMmuAccess, Is5LevelPaging);
if (SecondLevelPagingEntry == NULL) {
return NULL;
}
if (mAbove4GMemoryLimit != 0) {
ASSERT (mAbove4GMemoryLimit > BASE_4GB);
- SecondLevelPagingEntry = CreateSecondLevelPagingEntryTable (VtdIndex, SecondLevelPagingEntry, SIZE_4GB, mAbove4GMemoryLimit, IoMmuAccess);
+ SecondLevelPagingEntry = CreateSecondLevelPagingEntryTable (VtdIndex, SecondLevelPagingEntry, SIZE_4GB, mAbove4GMemoryLimit, IoMmuAccess, Is5LevelPaging);
if (SecondLevelPagingEntry == NULL) {
return NULL;
}
@@ -326,11 +400,13 @@ SetupTranslationTable (
/**
Dump DMAR context entry table.
- @param[in] RootEntry DMAR root entry.
+ @param[in] RootEntry DMAR root entry.
+ @param[in] Is5LevelPaging If it is the 5 level paging.
**/
VOID
DumpDmarContextEntryTable (
- IN VTD_ROOT_ENTRY *RootEntry
+ IN VTD_ROOT_ENTRY *RootEntry,
+ IN BOOLEAN Is5LevelPaging
)
{
UINTN Index;
@@ -359,7 +435,7 @@ DumpDmarContextEntryTable (
if (ContextEntry[Index2].Bits.Present == 0) {
continue;
}
- DumpSecondLevelPagingEntry ((VOID *)(UINTN)VTD_64BITS_ADDRESS(ContextEntry[Index2].Bits.SecondLevelPageTranslationPointerLo, ContextEntry[Index2].Bits.SecondLevelPageTranslationPointerHi));
+ DumpSecondLevelPagingEntry ((VOID *)(UINTN)VTD_64BITS_ADDRESS(ContextEntry[Index2].Bits.SecondLevelPageTranslationPointerLo, ContextEntry[Index2].Bits.SecondLevelPageTranslationPointerHi), Is5LevelPaging);
}
}
DEBUG ((DEBUG_INFO,"=========================\n"));
@@ -368,17 +444,22 @@ DumpDmarContextEntryTable (
/**
Dump DMAR second level paging entry.
- @param[in] SecondLevelPagingEntry The second level paging entry.
+ @param[in] SecondLevelPagingEntry The second level paging entry.
+ @param[in] Is5LevelPaging If it is the 5 level paging.
**/
VOID
DumpSecondLevelPagingEntry (
- IN VOID *SecondLevelPagingEntry
+ IN VOID *SecondLevelPagingEntry,
+ IN BOOLEAN Is5LevelPaging
)
{
+ UINTN Index5;
UINTN Index4;
UINTN Index3;
UINTN Index2;
UINTN Index1;
+ UINTN Lvl5IndexEnd;
+ VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl5PtEntry;
VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl4PtEntry;
VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl3PtEntry;
VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl2PtEntry;
@@ -386,38 +467,53 @@ DumpSecondLevelPagingEntry (
DEBUG ((DEBUG_VERBOSE,"================\n"));
DEBUG ((DEBUG_VERBOSE,"DMAR Second Level Page Table:\n"));
+ DEBUG ((DEBUG_VERBOSE,"SecondLevelPagingEntry Base - 0x%x, Is5LevelPaging - %d\n", SecondLevelPagingEntry, Is5LevelPaging));
- DEBUG ((DEBUG_VERBOSE,"SecondLevelPagingEntry Base - 0x%x\n", SecondLevelPagingEntry));
+ Lvl5IndexEnd = Is5LevelPaging ? SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY) : 1;
Lvl4PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY *)SecondLevelPagingEntry;
- for (Index4 = 0; Index4 < SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY); Index4++) {
- if (Lvl4PtEntry[Index4].Uint64 != 0) {
- DEBUG ((DEBUG_VERBOSE," Lvl4Pt Entry(0x%03x) - 0x%016lx\n", Index4, Lvl4PtEntry[Index4].Uint64));
- }
- if (Lvl4PtEntry[Index4].Uint64 == 0) {
- continue;
- }
- Lvl3PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY *)(UINTN)VTD_64BITS_ADDRESS(Lvl4PtEntry[Index4].Bits.AddressLo, Lvl4PtEntry[Index4].Bits.AddressHi);
- for (Index3 = 0; Index3 < SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY); Index3++) {
- if (Lvl3PtEntry[Index3].Uint64 != 0) {
- DEBUG ((DEBUG_VERBOSE," Lvl3Pt Entry(0x%03x) - 0x%016lx\n", Index3, Lvl3PtEntry[Index3].Uint64));
+ Lvl5PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY *)SecondLevelPagingEntry;
+
+ for (Index5 = 0; Index5 < Lvl5IndexEnd; Index5++) {
+ if (Is5LevelPaging) {
+ if (Lvl5PtEntry[Index5].Uint64 != 0) {
+ DEBUG ((DEBUG_VERBOSE," Lvl5Pt Entry(0x%03x) - 0x%016lx\n", Index5, Lvl5PtEntry[Index5].Uint64));
}
- if (Lvl3PtEntry[Index3].Uint64 == 0) {
+ if (Lvl5PtEntry[Index5].Uint64 == 0) {
continue;
}
+ Lvl4PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY *)(UINTN)VTD_64BITS_ADDRESS(Lvl5PtEntry[Index5].Bits.AddressLo, Lvl5PtEntry[Index5].Bits.AddressHi);
+ }
- Lvl2PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY *)(UINTN)VTD_64BITS_ADDRESS(Lvl3PtEntry[Index3].Bits.AddressLo, Lvl3PtEntry[Index3].Bits.AddressHi);
- for (Index2 = 0; Index2 < SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY); Index2++) {
- if (Lvl2PtEntry[Index2].Uint64 != 0) {
- DEBUG ((DEBUG_VERBOSE," Lvl2Pt Entry(0x%03x) - 0x%016lx\n", Index2, Lvl2PtEntry[Index2].Uint64));
+ for (Index4 = 0; Index4 < SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY); Index4++) {
+ if (Lvl4PtEntry[Index4].Uint64 != 0) {
+ DEBUG ((DEBUG_VERBOSE," Lvl4Pt Entry(0x%03x) - 0x%016lx\n", Index4, Lvl4PtEntry[Index4].Uint64));
+ }
+ if (Lvl4PtEntry[Index4].Uint64 == 0) {
+ continue;
+ }
+ Lvl3PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY *)(UINTN)VTD_64BITS_ADDRESS(Lvl4PtEntry[Index4].Bits.AddressLo, Lvl4PtEntry[Index4].Bits.AddressHi);
+ for (Index3 = 0; Index3 < SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY); Index3++) {
+ if (Lvl3PtEntry[Index3].Uint64 != 0) {
+ DEBUG ((DEBUG_VERBOSE," Lvl3Pt Entry(0x%03x) - 0x%016lx\n", Index3, Lvl3PtEntry[Index3].Uint64));
}
- if (Lvl2PtEntry[Index2].Uint64 == 0) {
+ if (Lvl3PtEntry[Index3].Uint64 == 0) {
continue;
}
- if (Lvl2PtEntry[Index2].Bits.PageSize == 0) {
- Lvl1PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY *)(UINTN)VTD_64BITS_ADDRESS(Lvl2PtEntry[Index2].Bits.AddressLo, Lvl2PtEntry[Index2].Bits.AddressHi);
- for (Index1 = 0; Index1 < SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY); Index1++) {
- if (Lvl1PtEntry[Index1].Uint64 != 0) {
- DEBUG ((DEBUG_VERBOSE," Lvl1Pt Entry(0x%03x) - 0x%016lx\n", Index1, Lvl1PtEntry[Index1].Uint64));
+
+ Lvl2PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY *)(UINTN)VTD_64BITS_ADDRESS(Lvl3PtEntry[Index3].Bits.AddressLo, Lvl3PtEntry[Index3].Bits.AddressHi);
+ for (Index2 = 0; Index2 < SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY); Index2++) {
+ if (Lvl2PtEntry[Index2].Uint64 != 0) {
+ DEBUG ((DEBUG_VERBOSE," Lvl2Pt Entry(0x%03x) - 0x%016lx\n", Index2, Lvl2PtEntry[Index2].Uint64));
+ }
+ if (Lvl2PtEntry[Index2].Uint64 == 0) {
+ continue;
+ }
+ if (Lvl2PtEntry[Index2].Bits.PageSize == 0) {
+ Lvl1PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY *)(UINTN)VTD_64BITS_ADDRESS(Lvl2PtEntry[Index2].Bits.AddressLo, Lvl2PtEntry[Index2].Bits.AddressHi);
+ for (Index1 = 0; Index1 < SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY); Index1++) {
+ if (Lvl1PtEntry[Index1].Uint64 != 0) {
+ DEBUG ((DEBUG_VERBOSE," Lvl1Pt Entry(0x%03x) - 0x%016lx\n", Index1, Lvl1PtEntry[Index1].Uint64));
+ }
}
}
}
@@ -510,6 +606,7 @@ PageAttributeToLength (
@param[in] VtdIndex The index used to identify a VTd engine.
@param[in] SecondLevelPagingEntry The second level paging entry in VTd table for the device.
@param[in] Address The address to be checked.
+ @param[in] Is5LevelPaging If it is the 5 level paging.
@param[out] PageAttributes The page attribute of the page entry.
@return The page entry.
@@ -519,6 +616,7 @@ GetSecondLevelPageTableEntry (
IN UINTN VtdIndex,
IN VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry,
IN PHYSICAL_ADDRESS Address,
+ IN BOOLEAN Is5LevelPaging,
OUT PAGE_ATTRIBUTE *PageAttribute
)
{
@@ -526,17 +624,38 @@ GetSecondLevelPageTableEntry (
UINTN Index2;
UINTN Index3;
UINTN Index4;
+ UINTN Index5;
UINT64 *L1PageTable;
UINT64 *L2PageTable;
UINT64 *L3PageTable;
UINT64 *L4PageTable;
+ UINT64 *L5PageTable;
+ Index5 = ((UINTN)RShiftU64 (Address, 48)) & PAGING_VTD_INDEX_MASK;
Index4 = ((UINTN)RShiftU64 (Address, 39)) & PAGING_VTD_INDEX_MASK;
Index3 = ((UINTN)Address >> 30) & PAGING_VTD_INDEX_MASK;
Index2 = ((UINTN)Address >> 21) & PAGING_VTD_INDEX_MASK;
Index1 = ((UINTN)Address >> 12) & PAGING_VTD_INDEX_MASK;
- L4PageTable = (UINT64 *)SecondLevelPagingEntry;
+ if (Is5LevelPaging) {
+ L5PageTable = (UINT64 *)SecondLevelPagingEntry;
+ if (L5PageTable[Index5] == 0) {
+ L5PageTable[Index5] = (UINT64)(UINTN)AllocateZeroPages (1);
+ if (L5PageTable[Index5] == 0) {
+ DEBUG ((DEBUG_ERROR,"!!!!!! ALLOCATE LVL5 PAGE FAIL (0x%x)!!!!!!\n", Index4));
+ ASSERT(FALSE);
+ *PageAttribute = PageNone;
+ return NULL;
+ }
+ FlushPageTableMemory (VtdIndex, (UINTN)L5PageTable[Index5], SIZE_4KB);
+ SetSecondLevelPagingEntryAttribute ((VTD_SECOND_LEVEL_PAGING_ENTRY *)&L5PageTable[Index5], EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);
+ FlushPageTableMemory (VtdIndex, (UINTN)&L5PageTable[Index5], sizeof(L5PageTable[Index5]));
+ }
+ L4PageTable = (UINT64 *)(UINTN)(L5PageTable[Index5] & PAGING_4K_ADDRESS_MASK_64);
+ } else {
+ L4PageTable = (UINT64 *)SecondLevelPagingEntry;
+ }
+
if (L4PageTable[Index4] == 0) {
L4PageTable[Index4] = (UINT64)(UINTN)AllocateZeroPages (1);
if (L4PageTable[Index4] == 0) {
@@ -785,7 +904,7 @@ SetSecondLevelPagingAttribute (
}
while (Length != 0) {
- PageEntry = GetSecondLevelPageTableEntry (VtdIndex, SecondLevelPagingEntry, BaseAddress, &PageAttribute);
+ PageEntry = GetSecondLevelPageTableEntry (VtdIndex, SecondLevelPagingEntry, BaseAddress, mVtdUnitInformation[VtdIndex].Is5LevelPaging, &PageAttribute);
if (PageEntry == NULL) {
DEBUG ((DEBUG_ERROR, "PageEntry - NULL\n"));
return RETURN_UNSUPPORTED;
@@ -913,7 +1032,7 @@ SetAccessAttribute (
if (ExtContextEntry != NULL) {
if (ExtContextEntry->Bits.Present == 0) {
- SecondLevelPagingEntry = CreateSecondLevelPagingEntry (VtdIndex, 0);
+ SecondLevelPagingEntry = CreateSecondLevelPagingEntry (VtdIndex, 0, mVtdUnitInformation[VtdIndex].Is5LevelPaging);
DEBUG ((DEBUG_VERBOSE,"SecondLevelPagingEntry - 0x%x (S%04x B%02x D%02x F%02x) New\n", SecondLevelPagingEntry, Segment, SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.Function));
Pt = (UINT64)RShiftU64 ((UINT64)(UINTN)SecondLevelPagingEntry, 12);
@@ -922,7 +1041,7 @@ SetAccessAttribute (
ExtContextEntry->Bits.DomainIdentifier = DomainIdentifier;
ExtContextEntry->Bits.Present = 1;
FlushPageTableMemory (VtdIndex, (UINTN)ExtContextEntry, sizeof(*ExtContextEntry));
- DumpDmarExtContextEntryTable (mVtdUnitInformation[VtdIndex].ExtRootEntryTable);
+ DumpDmarExtContextEntryTable (mVtdUnitInformation[VtdIndex].ExtRootEntryTable, mVtdUnitInformation[VtdIndex].Is5LevelPaging);
mVtdUnitInformation[VtdIndex].HasDirtyContext = TRUE;
} else {
SecondLevelPagingEntry = (VOID *)(UINTN)VTD_64BITS_ADDRESS(ExtContextEntry->Bits.SecondLevelPageTranslationPointerLo, ExtContextEntry->Bits.SecondLevelPageTranslationPointerHi);
@@ -930,7 +1049,7 @@ SetAccessAttribute (
}
} else if (ContextEntry != NULL) {
if (ContextEntry->Bits.Present == 0) {
- SecondLevelPagingEntry = CreateSecondLevelPagingEntry (VtdIndex, 0);
+ SecondLevelPagingEntry = CreateSecondLevelPagingEntry (VtdIndex, 0, mVtdUnitInformation[VtdIndex].Is5LevelPaging);
DEBUG ((DEBUG_VERBOSE,"SecondLevelPagingEntry - 0x%x (S%04x B%02x D%02x F%02x) New\n", SecondLevelPagingEntry, Segment, SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.Function));
Pt = (UINT64)RShiftU64 ((UINT64)(UINTN)SecondLevelPagingEntry, 12);
@@ -939,7 +1058,7 @@ SetAccessAttribute (
ContextEntry->Bits.DomainIdentifier = DomainIdentifier;
ContextEntry->Bits.Present = 1;
FlushPageTableMemory (VtdIndex, (UINTN)ContextEntry, sizeof(*ContextEntry));
- DumpDmarContextEntryTable (mVtdUnitInformation[VtdIndex].RootEntryTable);
+ DumpDmarContextEntryTable (mVtdUnitInformation[VtdIndex].RootEntryTable, mVtdUnitInformation[VtdIndex].Is5LevelPaging);
mVtdUnitInformation[VtdIndex].HasDirtyContext = TRUE;
} else {
SecondLevelPagingEntry = (VOID *)(UINTN)VTD_64BITS_ADDRESS(ContextEntry->Bits.SecondLevelPageTranslationPointerLo, ContextEntry->Bits.SecondLevelPageTranslationPointerHi);
@@ -1000,7 +1119,7 @@ AlwaysEnablePageAttribute (
if (mVtdUnitInformation[VtdIndex].FixedSecondLevelPagingEntry == 0) {
DEBUG((DEBUG_INFO, "CreateSecondLevelPagingEntry - %d\n", VtdIndex));
- mVtdUnitInformation[VtdIndex].FixedSecondLevelPagingEntry = CreateSecondLevelPagingEntry (VtdIndex, EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);
+ mVtdUnitInformation[VtdIndex].FixedSecondLevelPagingEntry = CreateSecondLevelPagingEntry (VtdIndex, EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE, mVtdUnitInformation[VtdIndex].Is5LevelPaging);
}
SecondLevelPagingEntry = mVtdUnitInformation[VtdIndex].FixedSecondLevelPagingEntry;
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTableEx.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTableEx.c
index 0ed9e3ca..3918eeee 100644
--- a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTableEx.c
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTableEx.c
@@ -78,11 +78,32 @@ CreateExtContextEntry (
DEBUG ((DEBUG_INFO,"DOMAIN: S%04x, B%02x D%02x F%02x\n", mVtdUnitInformation[VtdIndex].Segment, SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.Function));
- if ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW & BIT2) == 0) {
- DEBUG((DEBUG_ERROR, "!!!! 4-level page-table is not supported on VTD %d !!!!\n", VtdIndex));
+ mVtdUnitInformation[VtdIndex].Is5LevelPaging = FALSE;
+ if ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW & BIT3) != 0) {
+ if ((PcdGet8(PcdVTdPolicyPropertyMask) & BIT3) != 0) {
+ DEBUG((DEBUG_ERROR, "Force to use 4-level page-table on VTD %d\n", VtdIndex));
+ ExtContextEntry->Bits.AddressWidth = 0x2;
+ } if ((PcdGet8(PcdVTdPolicyPropertyMask) & BIT4) != 0) {
+ DEBUG((DEBUG_ERROR, "Force to use 5-level page-table on VTD %d\n", VtdIndex));
+ ExtContextEntry->Bits.AddressWidth = 0x3;
+ mVtdUnitInformation[VtdIndex].Is5LevelPaging = TRUE;
+ } else {
+ if (mAcpiDmarTable->HostAddressWidth > 48) {
+ DEBUG((DEBUG_ERROR, "Using 5-level page-table on VTD %d\n", VtdIndex));
+ ExtContextEntry->Bits.AddressWidth = 0x3;
+ mVtdUnitInformation[VtdIndex].Is5LevelPaging = TRUE;
+ } else {
+ DEBUG((DEBUG_ERROR, "Using 4-level page-table on VTD %d\n", VtdIndex));
+ ExtContextEntry->Bits.AddressWidth = 0x2;
+ }
+ }
+ } else if ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW & BIT2) != 0) {
+ DEBUG((DEBUG_ERROR, "Using 4-level page-table on VTD %d\n", VtdIndex));
+ ExtContextEntry->Bits.AddressWidth = 0x2;
+ } else {
+ DEBUG((DEBUG_ERROR, "!!!! Page-table type is not supported on VTD %d !!!!\n", VtdIndex));
return EFI_UNSUPPORTED;
}
- ExtContextEntry->Bits.AddressWidth = 0x2;
}
FlushPageTableMemory (VtdIndex, (UINTN)mVtdUnitInformation[VtdIndex].ExtRootEntryTable, EFI_PAGES_TO_SIZE(EntryTablePages));
@@ -93,11 +114,13 @@ CreateExtContextEntry (
/**
Dump DMAR extended context entry table.
- @param[in] ExtRootEntry DMAR extended root entry.
+ @param[in] ExtRootEntry DMAR extended root entry.
+ @param[in] Is5LevelPaging If it is the 5 level paging.
**/
VOID
DumpDmarExtContextEntryTable (
- IN VTD_EXT_ROOT_ENTRY *ExtRootEntry
+ IN VTD_EXT_ROOT_ENTRY *ExtRootEntry,
+ IN BOOLEAN Is5LevelPaging
)
{
UINTN Index;
@@ -127,7 +150,7 @@ DumpDmarExtContextEntryTable (
if (ExtContextEntry[Index2].Bits.Present == 0) {
continue;
}
- DumpSecondLevelPagingEntry ((VOID *)(UINTN)VTD_64BITS_ADDRESS(ExtContextEntry[Index2].Bits.SecondLevelPageTranslationPointerLo, ExtContextEntry[Index2].Bits.SecondLevelPageTranslationPointerHi));
+ DumpSecondLevelPagingEntry ((VOID *)(UINTN)VTD_64BITS_ADDRESS(ExtContextEntry[Index2].Bits.SecondLevelPageTranslationPointerLo, ExtContextEntry[Index2].Bits.SecondLevelPageTranslationPointerHi), Is5LevelPaging);
}
if (ExtRootEntry[Index].Bits.UpperPresent == 0) {
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/VtdReg.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/VtdReg.c
index 699639ba..686d235f 100644
--- a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/VtdReg.c
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/VtdReg.c
@@ -174,8 +174,14 @@ PrepareVtdConfig (
if ((mVtdUnitInformation[Index].CapReg.Bits.SLLPS & BIT0) == 0) {
DEBUG((DEBUG_WARN, "!!!! 2MB super page is not supported on VTD %d !!!!\n", Index));
}
- if ((mVtdUnitInformation[Index].CapReg.Bits.SAGAW & BIT2) == 0) {
- DEBUG((DEBUG_ERROR, "!!!! 4-level page-table is not supported on VTD %d !!!!\n", Index));
+ if ((mVtdUnitInformation[Index].CapReg.Bits.SAGAW & BIT3) != 0) {
+ DEBUG((DEBUG_INFO, "Support 5-level page-table on VTD %d\n", Index));
+ }
+ if ((mVtdUnitInformation[Index].CapReg.Bits.SAGAW & BIT2) != 0) {
+ DEBUG((DEBUG_INFO, "Support 4-level page-table on VTD %d\n", Index));
+ }
+ if ((mVtdUnitInformation[Index].CapReg.Bits.SAGAW & (BIT3 | BIT2)) == 0) {
+ DEBUG((DEBUG_ERROR, "!!!! Page-table type 0x%X is not supported on VTD %d !!!!\n", Index, mVtdUnitInformation[Index].CapReg.Bits.SAGAW));
return ;
}
diff --git a/Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dec b/Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dec
index 284820af..8f1edfe2 100644
--- a/Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dec
+++ b/Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dec
@@ -95,6 +95,9 @@
# BIT0: Enable IOMMU during boot (If DMAR table is installed in DXE. If VTD_INFO_PPI is installed in PEI.)
# BIT1: Enable IOMMU when transfer control to OS (ExitBootService in normal boot. EndOfPEI in S3)
# BIT2: Force no IOMMU access attribute request recording before DMAR table is installed.
+ # BIT3: Force to use 4 level paging.
+ # BIT4: If iommu support 5 level paging, force to use 5 level paging.
+ # (If both BIT3 and BIT4 are set, force to use 4 level paging.)
# @Prompt The policy for VTd driver behavior.
gIntelSiliconPkgTokenSpaceGuid.PcdVTdPolicyPropertyMask|1|UINT8|0x00000002
--
2.16.2.windows.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH v3] IntelSiliconPkg/VTd: Add iommu 5 level paging support
2020-11-18 1:17 [PATCH v3] IntelSiliconPkg/VTd: Add iommu 5 level paging support Sheng Wei
@ 2020-11-18 1:39 ` Yao, Jiewen
2020-11-18 2:33 ` Sheng Wei
0 siblings, 1 reply; 6+ messages in thread
From: Yao, Jiewen @ 2020-11-18 1:39 UTC (permalink / raw)
To: Sheng, W, devel@edk2.groups.io
Cc: Ni, Ray, Chaganty, Rangasai V, Huang, Jenny
Hi
I have 2 comments:
1) below capability check seems not correct.
(SAGAW & BIT3) is for 5 level only.
We need check (SAGAW & BIT2) for 4 level. But I do not see the code. Do I miss something?
if ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW & BIT3) != 0) {
if ((PcdGet8(PcdVTdPolicyPropertyMask) & BIT3) != 0) {
DEBUG((DEBUG_ERROR, "Force to use 4-level page-table on VTD %d\n", VtdIndex));
ContextEntry->Bits.AddressWidth = 0x2;
} if ((PcdGet8(PcdVTdPolicyPropertyMask) & BIT4) != 0) {
DEBUG((DEBUG_ERROR, "Force to use 5-level page-table on VTD %d\n", VtdIndex));
ContextEntry->Bits.AddressWidth = 0x3;
mVtdUnitInformation[VtdIndex].Is5LevelPaging = TRUE;
} else {
if (mAcpiDmarTable->HostAddressWidth > 48) {
DEBUG((DEBUG_ERROR, "Using 5-level page-table on VTD %d\n", VtdIndex));
ContextEntry->Bits.AddressWidth = 0x3;
mVtdUnitInformation[VtdIndex].Is5LevelPaging = TRUE;
} else {
DEBUG((DEBUG_ERROR, "Using 4-level page-table on VTD %d\n", VtdIndex));
ContextEntry->Bits.AddressWidth = 0x2;
}
}
2) I am wondering, do we really need 2 bit for level selection ?
What if force 4 level, but the platform does not support?
What if force 5 level, but the platform does not support?
# BIT3: Force to use 4 level paging.
# BIT4: If iommu support 5 level paging, force to use 5 level paging.
# (If both BIT3 and BIT4 are set, force to use 4 level paging.)
gIntelSiliconPkgTokenSpaceGuid.PcdVTdPolicyPropertyMask|1|UINT8|0x00000002
Can we align the solution in DXE/SMM paging solution?
> -----Original Message-----
> From: Sheng, W <w.sheng@intel.com>
> Sent: Wednesday, November 18, 2020 9:18 AM
> To: devel@edk2.groups.io
> Cc: Ni, Ray <ray.ni@intel.com>; Chaganty, Rangasai V
> <rangasai.v.chaganty@intel.com>; Yao, Jiewen <jiewen.yao@intel.com>;
> Huang, Jenny <jenny.huang@intel.com>
> Subject: [PATCH v3] IntelSiliconPkg/VTd: Add iommu 5 level paging support
>
> Support iommu 5 level paging for translation table.
>
> REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3067
>
> 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: Jiewen Yao <jiewen.yao@intel.com>
> Cc: Jenny Huang <jenny.huang@intel.com>
> ---
> .../Feature/VTd/IntelVTdDxe/DmaProtection.c | 4 +-
> .../Feature/VTd/IntelVTdDxe/DmaProtection.h | 19 +-
> .../Feature/VTd/IntelVTdDxe/TranslationTable.c | 287 +++++++++++++++--
> ----
> .../Feature/VTd/IntelVTdDxe/TranslationTableEx.c | 35 ++-
> .../Feature/VTd/IntelVTdDxe/VtdReg.c | 10 +-
> Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dec | 3 +
> 6 files changed, 258 insertions(+), 100 deletions(-)
>
> diff --git
> a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.c
> b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.c
> index 9b6135ef..628565ee 100644
> --- a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.c
> +++
> b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.c
> @@ -523,10 +523,10 @@ SetupVtd (
> for (Index = 0; Index < mVtdUnitNumber; Index++) {
> DEBUG ((DEBUG_INFO,"VTD Unit %d (Segment: %04x)\n", Index,
> mVtdUnitInformation[Index].Segment));
> if (mVtdUnitInformation[Index].ExtRootEntryTable != NULL) {
> - DumpDmarExtContextEntryTable
> (mVtdUnitInformation[Index].ExtRootEntryTable);
> + DumpDmarExtContextEntryTable
> (mVtdUnitInformation[Index].ExtRootEntryTable,
> mVtdUnitInformation[Index].Is5LevelPaging);
> }
> if (mVtdUnitInformation[Index].RootEntryTable != NULL) {
> - DumpDmarContextEntryTable
> (mVtdUnitInformation[Index].RootEntryTable);
> + DumpDmarContextEntryTable
> (mVtdUnitInformation[Index].RootEntryTable,
> mVtdUnitInformation[Index].Is5LevelPaging);
> }
> }
>
> diff --git
> a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.h
> b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.h
> index a3331db8..f641cea0 100644
> --- a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.h
> +++
> b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.h
> @@ -77,6 +77,7 @@ typedef struct {
> BOOLEAN HasDirtyContext;
> BOOLEAN HasDirtyPages;
> PCI_DEVICE_INFORMATION PciDeviceInfo;
> + BOOLEAN Is5LevelPaging;
> } VTD_UNIT_INFORMATION;
>
> //
> @@ -375,31 +376,37 @@ ParseDmarAcpiTableRmrr (
> /**
> Dump DMAR context entry table.
>
> - @param[in] RootEntry DMAR root entry.
> + @param[in] RootEntry DMAR root entry.
> + @param[in] Is5LevelPaging If it is the 5 level paging.
> **/
> VOID
> DumpDmarContextEntryTable (
> - IN VTD_ROOT_ENTRY *RootEntry
> + IN VTD_ROOT_ENTRY *RootEntry,
> + IN BOOLEAN Is5LevelPaging
> );
>
> /**
> Dump DMAR extended context entry table.
>
> - @param[in] ExtRootEntry DMAR extended root entry.
> + @param[in] ExtRootEntry DMAR extended root entry.
> + @param[in] Is5LevelPaging If it is the 5 level paging.
> **/
> VOID
> DumpDmarExtContextEntryTable (
> - IN VTD_EXT_ROOT_ENTRY *ExtRootEntry
> + IN VTD_EXT_ROOT_ENTRY *ExtRootEntry,
> + IN BOOLEAN Is5LevelPaging
> );
>
> /**
> Dump DMAR second level paging entry.
>
> - @param[in] SecondLevelPagingEntry The second level paging entry.
> + @param[in] SecondLevelPagingEntry The second level paging entry.
> + @param[in] Is5LevelPaging If it is the 5 level paging.
> **/
> VOID
> DumpSecondLevelPagingEntry (
> - IN VOID *SecondLevelPagingEntry
> + IN VOID *SecondLevelPagingEntry,
> + IN BOOLEAN Is5LevelPaging
> );
>
> /**
> diff --git
> a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTable.c
> b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTable.c
> index 201d663d..cb59860a 100644
> ---
> a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTable.c
> +++
> b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTable.c
> @@ -128,11 +128,32 @@ CreateContextEntry (
>
> DEBUG ((DEBUG_INFO,"Source: S%04x B%02x D%02x F%02x\n",
> mVtdUnitInformation[VtdIndex].Segment, SourceId.Bits.Bus,
> SourceId.Bits.Device, SourceId.Bits.Function));
>
> - if ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW & BIT2) == 0) {
> - DEBUG((DEBUG_ERROR, "!!!! 4-level page-table is not supported on
> VTD %d !!!!\n", VtdIndex));
> + mVtdUnitInformation[VtdIndex].Is5LevelPaging = FALSE;
> + if ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW & BIT3) != 0) {
> + if ((PcdGet8(PcdVTdPolicyPropertyMask) & BIT3) != 0) {
> + DEBUG((DEBUG_ERROR, "Force to use 4-level page-table on VTD %d\n",
> VtdIndex));
> + ContextEntry->Bits.AddressWidth = 0x2;
> + } if ((PcdGet8(PcdVTdPolicyPropertyMask) & BIT4) != 0) {
> + DEBUG((DEBUG_ERROR, "Force to use 5-level page-table on VTD %d\n",
> VtdIndex));
> + ContextEntry->Bits.AddressWidth = 0x3;
> + mVtdUnitInformation[VtdIndex].Is5LevelPaging = TRUE;
> + } else {
> + if (mAcpiDmarTable->HostAddressWidth > 48) {
> + DEBUG((DEBUG_ERROR, "Using 5-level page-table on VTD %d\n",
> VtdIndex));
> + ContextEntry->Bits.AddressWidth = 0x3;
> + mVtdUnitInformation[VtdIndex].Is5LevelPaging = TRUE;
> + } else {
> + DEBUG((DEBUG_ERROR, "Using 4-level page-table on VTD %d\n",
> VtdIndex));
> + ContextEntry->Bits.AddressWidth = 0x2;
> + }
> + }
> + } else if ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW & BIT2) !=
> 0) {
> + DEBUG((DEBUG_ERROR, "Using 4-level page-table on VTD %d\n",
> VtdIndex));
> + ContextEntry->Bits.AddressWidth = 0x2;
> + } else {
> + DEBUG((DEBUG_ERROR, "!!!! Page-table type is not supported on
> VTD %d !!!!\n", VtdIndex));
> return EFI_UNSUPPORTED;
> }
> - ContextEntry->Bits.AddressWidth = 0x2;
> }
>
> FlushPageTableMemory (VtdIndex,
> (UINTN)mVtdUnitInformation[VtdIndex].RootEntryTable,
> EFI_PAGES_TO_SIZE(EntryTablePages));
> @@ -148,6 +169,7 @@ CreateContextEntry (
> @param[in] MemoryBase The base of the memory.
> @param[in] MemoryLimit The limit of the memory.
> @param[in] IoMmuAccess The IOMMU access.
> + @param[in] Is5LevelPaging If it is the 5 level paging.
>
> @return The second level paging entry.
> **/
> @@ -157,16 +179,23 @@ CreateSecondLevelPagingEntryTable (
> IN VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry,
> IN UINT64 MemoryBase,
> IN UINT64 MemoryLimit,
> - IN UINT64 IoMmuAccess
> + IN UINT64 IoMmuAccess,
> + IN BOOLEAN Is5LevelPaging
> )
> {
> + UINTN Index5;
> UINTN Index4;
> UINTN Index3;
> UINTN Index2;
> + UINTN Lvl5Start;
> + UINTN Lvl5End;
> + UINTN Lvl4PagesStart;
> + UINTN Lvl4PagesEnd;
> UINTN Lvl4Start;
> UINTN Lvl4End;
> UINTN Lvl3Start;
> UINTN Lvl3End;
> + VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl5PtEntry;
> VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl4PtEntry;
> VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl3PtEntry;
> VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl2PtEntry;
> @@ -184,7 +213,7 @@ CreateSecondLevelPagingEntryTable (
> if (SecondLevelPagingEntry == NULL) {
> SecondLevelPagingEntry = AllocateZeroPages (1);
> if (SecondLevelPagingEntry == NULL) {
> - DEBUG ((DEBUG_ERROR,"Could not Alloc LVL4 PT. \n"));
> + DEBUG ((DEBUG_ERROR,"Could not Alloc LVL4 or LVL5 PT. \n"));
> return NULL;
> }
> FlushPageTableMemory (VtdIndex, (UINTN)SecondLevelPagingEntry,
> EFI_PAGES_TO_SIZE(1));
> @@ -197,66 +226,109 @@ CreateSecondLevelPagingEntryTable (
> return SecondLevelPagingEntry;
> }
>
> - Lvl4Start = RShiftU64 (BaseAddress, 39) & 0x1FF;
> - Lvl4End = RShiftU64 (EndAddress - 1, 39) & 0x1FF;
> + if (Is5LevelPaging) {
> + Lvl5Start = RShiftU64 (BaseAddress, 48) & 0x1FF;
> + Lvl5End = RShiftU64 (EndAddress - 1, 48) & 0x1FF;
> + DEBUG ((DEBUG_INFO," Lvl5Start - 0x%x, Lvl5End - 0x%x\n", Lvl5Start,
> Lvl5End));
>
> - DEBUG ((DEBUG_INFO," Lvl4Start - 0x%x, Lvl4End - 0x%x\n", Lvl4Start,
> Lvl4End));
> + Lvl4Start = RShiftU64 (BaseAddress, 39) & 0x1FF;
> + Lvl4End = RShiftU64 (EndAddress - 1, 39) & 0x1FF;
>
> - Lvl4PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> *)SecondLevelPagingEntry;
> - for (Index4 = Lvl4Start; Index4 <= Lvl4End; Index4++) {
> - if (Lvl4PtEntry[Index4].Uint64 == 0) {
> - Lvl4PtEntry[Index4].Uint64 = (UINT64)(UINTN)AllocateZeroPages (1);
> - if (Lvl4PtEntry[Index4].Uint64 == 0) {
> - DEBUG ((DEBUG_ERROR,"!!!!!! ALLOCATE LVL4 PAGE FAIL
> (0x%x)!!!!!!\n", Index4));
> - ASSERT(FALSE);
> - return NULL;
> - }
> - FlushPageTableMemory (VtdIndex, (UINTN)Lvl4PtEntry[Index4].Uint64,
> SIZE_4KB);
> - SetSecondLevelPagingEntryAttribute (&Lvl4PtEntry[Index4],
> EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);
> - }
> + Lvl4PagesStart = (Lvl5Start<<9) | Lvl4Start;
> + Lvl4PagesEnd = (Lvl5End<<9) | Lvl4End;
> + DEBUG ((DEBUG_INFO," Lvl4PagesStart - 0x%x, Lvl4PagesEnd - 0x%x\n",
> Lvl4PagesStart, Lvl4PagesEnd));
>
> - Lvl3Start = RShiftU64 (BaseAddress, 30) & 0x1FF;
> - if (ALIGN_VALUE_LOW(BaseAddress + SIZE_1GB, SIZE_1GB) <=
> EndAddress) {
> - Lvl3End = SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY) - 1;
> - } else {
> - Lvl3End = RShiftU64 (EndAddress - 1, 30) & 0x1FF;
> + Lvl5PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> *)SecondLevelPagingEntry;
> + } else {
> + Lvl5Start = RShiftU64 (BaseAddress, 48) & 0x1FF;
> + Lvl5End = Lvl5Start;
> +
> + Lvl4Start = RShiftU64 (BaseAddress, 39) & 0x1FF;
> + Lvl4End = RShiftU64 (EndAddress - 1, 39) & 0x1FF;
> + DEBUG ((DEBUG_INFO," Lvl4Start - 0x%x, Lvl4End - 0x%x\n", Lvl4Start,
> Lvl4End));
> +
> + Lvl4PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> *)SecondLevelPagingEntry;
> + }
> +
> + for (Index5 = Lvl5Start; Index5 <= Lvl5End; Index5++) {
> + if (Is5LevelPaging) {
> + if (Lvl5PtEntry[Index5].Uint64 == 0) {
> + Lvl5PtEntry[Index5].Uint64 = (UINT64)(UINTN)AllocateZeroPages (1);
> + if (Lvl5PtEntry[Index5].Uint64 == 0) {
> + DEBUG ((DEBUG_ERROR,"!!!!!! ALLOCATE LVL4 PAGE FAIL
> (0x%x)!!!!!!\n", Index5));
> + ASSERT(FALSE);
> + return NULL;
> + }
> + FlushPageTableMemory (VtdIndex, (UINTN)Lvl5PtEntry[Index5].Uint64,
> SIZE_4KB);
> + SetSecondLevelPagingEntryAttribute (&Lvl5PtEntry[Index5],
> EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);
> + }
> + Lvl4Start = Lvl4PagesStart & 0x1FF;
> + if (((Index5+1)<<9) > Lvl4PagesEnd) {
> + Lvl4End = SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY) - 1;;
> + Lvl4PagesStart = (Index5+1)<<9;
> + } else {
> + Lvl4End = Lvl4PagesEnd & 0x1FF;
> + }
> + DEBUG ((DEBUG_INFO," Lvl5(0x%x): Lvl4Start - 0x%x, Lvl4End - 0x%x\n",
> Index5, Lvl4Start, Lvl4End));
> + Lvl4PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> *)(UINTN)VTD_64BITS_ADDRESS(Lvl5PtEntry[Index5].Bits.AddressLo,
> Lvl5PtEntry[Index5].Bits.AddressHi);
> }
> - DEBUG ((DEBUG_INFO," Lvl4(0x%x): Lvl3Start - 0x%x, Lvl3End - 0x%x\n",
> Index4, Lvl3Start, Lvl3End));
>
> - Lvl3PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> *)(UINTN)VTD_64BITS_ADDRESS(Lvl4PtEntry[Index4].Bits.AddressLo,
> Lvl4PtEntry[Index4].Bits.AddressHi);
> - for (Index3 = Lvl3Start; Index3 <= Lvl3End; Index3++) {
> - if (Lvl3PtEntry[Index3].Uint64 == 0) {
> - Lvl3PtEntry[Index3].Uint64 = (UINT64)(UINTN)AllocateZeroPages (1);
> - if (Lvl3PtEntry[Index3].Uint64 == 0) {
> - DEBUG ((DEBUG_ERROR,"!!!!!! ALLOCATE LVL3 PAGE FAIL (0x%x,
> 0x%x)!!!!!!\n", Index4, Index3));
> + for (Index4 = Lvl4Start; Index4 <= Lvl4End; Index4++) {
> + if (Lvl4PtEntry[Index4].Uint64 == 0) {
> + Lvl4PtEntry[Index4].Uint64 = (UINT64)(UINTN)AllocateZeroPages (1);
> + if (Lvl4PtEntry[Index4].Uint64 == 0) {
> + DEBUG ((DEBUG_ERROR,"!!!!!! ALLOCATE LVL4 PAGE FAIL
> (0x%x)!!!!!!\n", Index4));
> ASSERT(FALSE);
> return NULL;
> }
> - FlushPageTableMemory (VtdIndex, (UINTN)Lvl3PtEntry[Index3].Uint64,
> SIZE_4KB);
> - SetSecondLevelPagingEntryAttribute (&Lvl3PtEntry[Index3],
> EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);
> + FlushPageTableMemory (VtdIndex, (UINTN)Lvl4PtEntry[Index4].Uint64,
> SIZE_4KB);
> + SetSecondLevelPagingEntryAttribute (&Lvl4PtEntry[Index4],
> EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);
> }
>
> - Lvl2PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> *)(UINTN)VTD_64BITS_ADDRESS(Lvl3PtEntry[Index3].Bits.AddressLo,
> Lvl3PtEntry[Index3].Bits.AddressHi);
> - for (Index2 = 0; Index2 <
> SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY); Index2++) {
> - Lvl2PtEntry[Index2].Uint64 = BaseAddress;
> - SetSecondLevelPagingEntryAttribute (&Lvl2PtEntry[Index2],
> IoMmuAccess);
> - Lvl2PtEntry[Index2].Bits.PageSize = 1;
> - BaseAddress += SIZE_2MB;
> + Lvl3Start = RShiftU64 (BaseAddress, 30) & 0x1FF;
> + if (ALIGN_VALUE_LOW(BaseAddress + SIZE_1GB, SIZE_1GB) <=
> EndAddress) {
> + Lvl3End = SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY) - 1;
> + } else {
> + Lvl3End = RShiftU64 (EndAddress - 1, 30) & 0x1FF;
> + }
> + DEBUG ((DEBUG_INFO," Lvl4(0x%x): Lvl3Start - 0x%x, Lvl3End - 0x%x\n",
> Index4, Lvl3Start, Lvl3End));
> +
> + Lvl3PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> *)(UINTN)VTD_64BITS_ADDRESS(Lvl4PtEntry[Index4].Bits.AddressLo,
> Lvl4PtEntry[Index4].Bits.AddressHi);
> + for (Index3 = Lvl3Start; Index3 <= Lvl3End; Index3++) {
> + if (Lvl3PtEntry[Index3].Uint64 == 0) {
> + Lvl3PtEntry[Index3].Uint64 = (UINT64)(UINTN)AllocateZeroPages (1);
> + if (Lvl3PtEntry[Index3].Uint64 == 0) {
> + DEBUG ((DEBUG_ERROR,"!!!!!! ALLOCATE LVL3 PAGE FAIL (0x%x,
> 0x%x)!!!!!!\n", Index4, Index3));
> + ASSERT(FALSE);
> + return NULL;
> + }
> + FlushPageTableMemory (VtdIndex, (UINTN)Lvl3PtEntry[Index3].Uint64,
> SIZE_4KB);
> + SetSecondLevelPagingEntryAttribute (&Lvl3PtEntry[Index3],
> EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);
> + }
> +
> + Lvl2PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> *)(UINTN)VTD_64BITS_ADDRESS(Lvl3PtEntry[Index3].Bits.AddressLo,
> Lvl3PtEntry[Index3].Bits.AddressHi);
> + for (Index2 = 0; Index2 <
> SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY); Index2++) {
> + Lvl2PtEntry[Index2].Uint64 = BaseAddress;
> + SetSecondLevelPagingEntryAttribute (&Lvl2PtEntry[Index2],
> IoMmuAccess);
> + Lvl2PtEntry[Index2].Bits.PageSize = 1;
> + BaseAddress += SIZE_2MB;
> + if (BaseAddress >= MemoryLimit) {
> + break;
> + }
> + }
> + FlushPageTableMemory (VtdIndex, (UINTN)Lvl2PtEntry, SIZE_4KB);
> if (BaseAddress >= MemoryLimit) {
> break;
> }
> }
> - FlushPageTableMemory (VtdIndex, (UINTN)Lvl2PtEntry, SIZE_4KB);
> + FlushPageTableMemory (VtdIndex, (UINTN)&Lvl3PtEntry[Lvl3Start],
> (UINTN)&Lvl3PtEntry[Lvl3End + 1] - (UINTN)&Lvl3PtEntry[Lvl3Start]);
> if (BaseAddress >= MemoryLimit) {
> break;
> }
> }
> - FlushPageTableMemory (VtdIndex, (UINTN)&Lvl3PtEntry[Lvl3Start],
> (UINTN)&Lvl3PtEntry[Lvl3End + 1] - (UINTN)&Lvl3PtEntry[Lvl3Start]);
> - if (BaseAddress >= MemoryLimit) {
> - break;
> - }
> + FlushPageTableMemory (VtdIndex, (UINTN)&Lvl4PtEntry[Lvl4Start],
> (UINTN)&Lvl4PtEntry[Lvl4End + 1] - (UINTN)&Lvl4PtEntry[Lvl4Start]);
> }
> - FlushPageTableMemory (VtdIndex, (UINTN)&Lvl4PtEntry[Lvl4Start],
> (UINTN)&Lvl4PtEntry[Lvl4End + 1] - (UINTN)&Lvl4PtEntry[Lvl4Start]);
> + FlushPageTableMemory (VtdIndex, (UINTN)&Lvl5PtEntry[Lvl5Start],
> (UINTN)&Lvl5PtEntry[Lvl5End + 1] - (UINTN)&Lvl5PtEntry[Lvl5Start]);
>
> return SecondLevelPagingEntry;
> }
> @@ -266,26 +338,28 @@ CreateSecondLevelPagingEntryTable (
>
> @param[in] VtdIndex The index of the VTd engine.
> @param[in] IoMmuAccess The IOMMU access.
> + @param[in] Is5LevelPaging If it is the 5 level paging.
>
> @return The second level paging entry.
> **/
> VTD_SECOND_LEVEL_PAGING_ENTRY *
> CreateSecondLevelPagingEntry (
> IN UINTN VtdIndex,
> - IN UINT64 IoMmuAccess
> + IN UINT64 IoMmuAccess,
> + IN BOOLEAN Is5LevelPaging
> )
> {
> VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry;
>
> SecondLevelPagingEntry = NULL;
> - SecondLevelPagingEntry = CreateSecondLevelPagingEntryTable (VtdIndex,
> SecondLevelPagingEntry, 0, mBelow4GMemoryLimit, IoMmuAccess);
> + SecondLevelPagingEntry = CreateSecondLevelPagingEntryTable (VtdIndex,
> SecondLevelPagingEntry, 0, mBelow4GMemoryLimit, IoMmuAccess,
> Is5LevelPaging);
> if (SecondLevelPagingEntry == NULL) {
> return NULL;
> }
>
> if (mAbove4GMemoryLimit != 0) {
> ASSERT (mAbove4GMemoryLimit > BASE_4GB);
> - SecondLevelPagingEntry = CreateSecondLevelPagingEntryTable (VtdIndex,
> SecondLevelPagingEntry, SIZE_4GB, mAbove4GMemoryLimit, IoMmuAccess);
> + SecondLevelPagingEntry = CreateSecondLevelPagingEntryTable (VtdIndex,
> SecondLevelPagingEntry, SIZE_4GB, mAbove4GMemoryLimit, IoMmuAccess,
> Is5LevelPaging);
> if (SecondLevelPagingEntry == NULL) {
> return NULL;
> }
> @@ -326,11 +400,13 @@ SetupTranslationTable (
> /**
> Dump DMAR context entry table.
>
> - @param[in] RootEntry DMAR root entry.
> + @param[in] RootEntry DMAR root entry.
> + @param[in] Is5LevelPaging If it is the 5 level paging.
> **/
> VOID
> DumpDmarContextEntryTable (
> - IN VTD_ROOT_ENTRY *RootEntry
> + IN VTD_ROOT_ENTRY *RootEntry,
> + IN BOOLEAN Is5LevelPaging
> )
> {
> UINTN Index;
> @@ -359,7 +435,7 @@ DumpDmarContextEntryTable (
> if (ContextEntry[Index2].Bits.Present == 0) {
> continue;
> }
> - DumpSecondLevelPagingEntry ((VOID
> *)(UINTN)VTD_64BITS_ADDRESS(ContextEntry[Index2].Bits.SecondLevelPage
> TranslationPointerLo,
> ContextEntry[Index2].Bits.SecondLevelPageTranslationPointerHi));
> + DumpSecondLevelPagingEntry ((VOID
> *)(UINTN)VTD_64BITS_ADDRESS(ContextEntry[Index2].Bits.SecondLevelPage
> TranslationPointerLo,
> ContextEntry[Index2].Bits.SecondLevelPageTranslationPointerHi),
> Is5LevelPaging);
> }
> }
> DEBUG ((DEBUG_INFO,"=========================\n"));
> @@ -368,17 +444,22 @@ DumpDmarContextEntryTable (
> /**
> Dump DMAR second level paging entry.
>
> - @param[in] SecondLevelPagingEntry The second level paging entry.
> + @param[in] SecondLevelPagingEntry The second level paging entry.
> + @param[in] Is5LevelPaging If it is the 5 level paging.
> **/
> VOID
> DumpSecondLevelPagingEntry (
> - IN VOID *SecondLevelPagingEntry
> + IN VOID *SecondLevelPagingEntry,
> + IN BOOLEAN Is5LevelPaging
> )
> {
> + UINTN Index5;
> UINTN Index4;
> UINTN Index3;
> UINTN Index2;
> UINTN Index1;
> + UINTN Lvl5IndexEnd;
> + VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl5PtEntry;
> VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl4PtEntry;
> VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl3PtEntry;
> VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl2PtEntry;
> @@ -386,38 +467,53 @@ DumpSecondLevelPagingEntry (
>
> DEBUG ((DEBUG_VERBOSE,"================\n"));
> DEBUG ((DEBUG_VERBOSE,"DMAR Second Level Page Table:\n"));
> + DEBUG ((DEBUG_VERBOSE,"SecondLevelPagingEntry Base - 0x%x,
> Is5LevelPaging - %d\n", SecondLevelPagingEntry, Is5LevelPaging));
>
> - DEBUG ((DEBUG_VERBOSE,"SecondLevelPagingEntry Base - 0x%x\n",
> SecondLevelPagingEntry));
> + Lvl5IndexEnd = Is5LevelPaging ?
> SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY) : 1;
> Lvl4PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> *)SecondLevelPagingEntry;
> - for (Index4 = 0; Index4 <
> SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY); Index4++) {
> - if (Lvl4PtEntry[Index4].Uint64 != 0) {
> - DEBUG ((DEBUG_VERBOSE," Lvl4Pt Entry(0x%03x) - 0x%016lx\n", Index4,
> Lvl4PtEntry[Index4].Uint64));
> - }
> - if (Lvl4PtEntry[Index4].Uint64 == 0) {
> - continue;
> - }
> - Lvl3PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> *)(UINTN)VTD_64BITS_ADDRESS(Lvl4PtEntry[Index4].Bits.AddressLo,
> Lvl4PtEntry[Index4].Bits.AddressHi);
> - for (Index3 = 0; Index3 <
> SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY); Index3++) {
> - if (Lvl3PtEntry[Index3].Uint64 != 0) {
> - DEBUG ((DEBUG_VERBOSE," Lvl3Pt Entry(0x%03x) - 0x%016lx\n",
> Index3, Lvl3PtEntry[Index3].Uint64));
> + Lvl5PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> *)SecondLevelPagingEntry;
> +
> + for (Index5 = 0; Index5 < Lvl5IndexEnd; Index5++) {
> + if (Is5LevelPaging) {
> + if (Lvl5PtEntry[Index5].Uint64 != 0) {
> + DEBUG ((DEBUG_VERBOSE," Lvl5Pt Entry(0x%03x) - 0x%016lx\n",
> Index5, Lvl5PtEntry[Index5].Uint64));
> }
> - if (Lvl3PtEntry[Index3].Uint64 == 0) {
> + if (Lvl5PtEntry[Index5].Uint64 == 0) {
> continue;
> }
> + Lvl4PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> *)(UINTN)VTD_64BITS_ADDRESS(Lvl5PtEntry[Index5].Bits.AddressLo,
> Lvl5PtEntry[Index5].Bits.AddressHi);
> + }
>
> - Lvl2PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> *)(UINTN)VTD_64BITS_ADDRESS(Lvl3PtEntry[Index3].Bits.AddressLo,
> Lvl3PtEntry[Index3].Bits.AddressHi);
> - for (Index2 = 0; Index2 <
> SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY); Index2++) {
> - if (Lvl2PtEntry[Index2].Uint64 != 0) {
> - DEBUG ((DEBUG_VERBOSE," Lvl2Pt Entry(0x%03x) - 0x%016lx\n",
> Index2, Lvl2PtEntry[Index2].Uint64));
> + for (Index4 = 0; Index4 <
> SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY); Index4++) {
> + if (Lvl4PtEntry[Index4].Uint64 != 0) {
> + DEBUG ((DEBUG_VERBOSE," Lvl4Pt Entry(0x%03x) - 0x%016lx\n",
> Index4, Lvl4PtEntry[Index4].Uint64));
> + }
> + if (Lvl4PtEntry[Index4].Uint64 == 0) {
> + continue;
> + }
> + Lvl3PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> *)(UINTN)VTD_64BITS_ADDRESS(Lvl4PtEntry[Index4].Bits.AddressLo,
> Lvl4PtEntry[Index4].Bits.AddressHi);
> + for (Index3 = 0; Index3 <
> SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY); Index3++) {
> + if (Lvl3PtEntry[Index3].Uint64 != 0) {
> + DEBUG ((DEBUG_VERBOSE," Lvl3Pt Entry(0x%03x) - 0x%016lx\n",
> Index3, Lvl3PtEntry[Index3].Uint64));
> }
> - if (Lvl2PtEntry[Index2].Uint64 == 0) {
> + if (Lvl3PtEntry[Index3].Uint64 == 0) {
> continue;
> }
> - if (Lvl2PtEntry[Index2].Bits.PageSize == 0) {
> - Lvl1PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> *)(UINTN)VTD_64BITS_ADDRESS(Lvl2PtEntry[Index2].Bits.AddressLo,
> Lvl2PtEntry[Index2].Bits.AddressHi);
> - for (Index1 = 0; Index1 <
> SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY); Index1++) {
> - if (Lvl1PtEntry[Index1].Uint64 != 0) {
> - DEBUG ((DEBUG_VERBOSE," Lvl1Pt Entry(0x%03x) - 0x%016lx\n",
> Index1, Lvl1PtEntry[Index1].Uint64));
> +
> + Lvl2PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> *)(UINTN)VTD_64BITS_ADDRESS(Lvl3PtEntry[Index3].Bits.AddressLo,
> Lvl3PtEntry[Index3].Bits.AddressHi);
> + for (Index2 = 0; Index2 <
> SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY); Index2++) {
> + if (Lvl2PtEntry[Index2].Uint64 != 0) {
> + DEBUG ((DEBUG_VERBOSE," Lvl2Pt Entry(0x%03x) - 0x%016lx\n",
> Index2, Lvl2PtEntry[Index2].Uint64));
> + }
> + if (Lvl2PtEntry[Index2].Uint64 == 0) {
> + continue;
> + }
> + if (Lvl2PtEntry[Index2].Bits.PageSize == 0) {
> + Lvl1PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> *)(UINTN)VTD_64BITS_ADDRESS(Lvl2PtEntry[Index2].Bits.AddressLo,
> Lvl2PtEntry[Index2].Bits.AddressHi);
> + for (Index1 = 0; Index1 <
> SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY); Index1++) {
> + if (Lvl1PtEntry[Index1].Uint64 != 0) {
> + DEBUG ((DEBUG_VERBOSE," Lvl1Pt Entry(0x%03x) - 0x%016lx\n",
> Index1, Lvl1PtEntry[Index1].Uint64));
> + }
> }
> }
> }
> @@ -510,6 +606,7 @@ PageAttributeToLength (
> @param[in] VtdIndex The index used to identify a VTd engine.
> @param[in] SecondLevelPagingEntry The second level paging entry in
> VTd table for the device.
> @param[in] Address The address to be checked.
> + @param[in] Is5LevelPaging If it is the 5 level paging.
> @param[out] PageAttributes The page attribute of the page entry.
>
> @return The page entry.
> @@ -519,6 +616,7 @@ GetSecondLevelPageTableEntry (
> IN UINTN VtdIndex,
> IN VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry,
> IN PHYSICAL_ADDRESS Address,
> + IN BOOLEAN Is5LevelPaging,
> OUT PAGE_ATTRIBUTE *PageAttribute
> )
> {
> @@ -526,17 +624,38 @@ GetSecondLevelPageTableEntry (
> UINTN Index2;
> UINTN Index3;
> UINTN Index4;
> + UINTN Index5;
> UINT64 *L1PageTable;
> UINT64 *L2PageTable;
> UINT64 *L3PageTable;
> UINT64 *L4PageTable;
> + UINT64 *L5PageTable;
>
> + Index5 = ((UINTN)RShiftU64 (Address, 48)) & PAGING_VTD_INDEX_MASK;
> Index4 = ((UINTN)RShiftU64 (Address, 39)) & PAGING_VTD_INDEX_MASK;
> Index3 = ((UINTN)Address >> 30) & PAGING_VTD_INDEX_MASK;
> Index2 = ((UINTN)Address >> 21) & PAGING_VTD_INDEX_MASK;
> Index1 = ((UINTN)Address >> 12) & PAGING_VTD_INDEX_MASK;
>
> - L4PageTable = (UINT64 *)SecondLevelPagingEntry;
> + if (Is5LevelPaging) {
> + L5PageTable = (UINT64 *)SecondLevelPagingEntry;
> + if (L5PageTable[Index5] == 0) {
> + L5PageTable[Index5] = (UINT64)(UINTN)AllocateZeroPages (1);
> + if (L5PageTable[Index5] == 0) {
> + DEBUG ((DEBUG_ERROR,"!!!!!! ALLOCATE LVL5 PAGE FAIL
> (0x%x)!!!!!!\n", Index4));
> + ASSERT(FALSE);
> + *PageAttribute = PageNone;
> + return NULL;
> + }
> + FlushPageTableMemory (VtdIndex, (UINTN)L5PageTable[Index5],
> SIZE_4KB);
> + SetSecondLevelPagingEntryAttribute
> ((VTD_SECOND_LEVEL_PAGING_ENTRY *)&L5PageTable[Index5],
> EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);
> + FlushPageTableMemory (VtdIndex, (UINTN)&L5PageTable[Index5],
> sizeof(L5PageTable[Index5]));
> + }
> + L4PageTable = (UINT64 *)(UINTN)(L5PageTable[Index5] &
> PAGING_4K_ADDRESS_MASK_64);
> + } else {
> + L4PageTable = (UINT64 *)SecondLevelPagingEntry;
> + }
> +
> if (L4PageTable[Index4] == 0) {
> L4PageTable[Index4] = (UINT64)(UINTN)AllocateZeroPages (1);
> if (L4PageTable[Index4] == 0) {
> @@ -785,7 +904,7 @@ SetSecondLevelPagingAttribute (
> }
>
> while (Length != 0) {
> - PageEntry = GetSecondLevelPageTableEntry (VtdIndex,
> SecondLevelPagingEntry, BaseAddress, &PageAttribute);
> + PageEntry = GetSecondLevelPageTableEntry (VtdIndex,
> SecondLevelPagingEntry, BaseAddress,
> mVtdUnitInformation[VtdIndex].Is5LevelPaging, &PageAttribute);
> if (PageEntry == NULL) {
> DEBUG ((DEBUG_ERROR, "PageEntry - NULL\n"));
> return RETURN_UNSUPPORTED;
> @@ -913,7 +1032,7 @@ SetAccessAttribute (
>
> if (ExtContextEntry != NULL) {
> if (ExtContextEntry->Bits.Present == 0) {
> - SecondLevelPagingEntry = CreateSecondLevelPagingEntry (VtdIndex, 0);
> + SecondLevelPagingEntry = CreateSecondLevelPagingEntry (VtdIndex, 0,
> mVtdUnitInformation[VtdIndex].Is5LevelPaging);
> DEBUG ((DEBUG_VERBOSE,"SecondLevelPagingEntry - 0x%x (S%04x
> B%02x D%02x F%02x) New\n", SecondLevelPagingEntry, Segment,
> SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.Function));
> Pt = (UINT64)RShiftU64 ((UINT64)(UINTN)SecondLevelPagingEntry, 12);
>
> @@ -922,7 +1041,7 @@ SetAccessAttribute (
> ExtContextEntry->Bits.DomainIdentifier = DomainIdentifier;
> ExtContextEntry->Bits.Present = 1;
> FlushPageTableMemory (VtdIndex, (UINTN)ExtContextEntry,
> sizeof(*ExtContextEntry));
> - DumpDmarExtContextEntryTable
> (mVtdUnitInformation[VtdIndex].ExtRootEntryTable);
> + DumpDmarExtContextEntryTable
> (mVtdUnitInformation[VtdIndex].ExtRootEntryTable,
> mVtdUnitInformation[VtdIndex].Is5LevelPaging);
> mVtdUnitInformation[VtdIndex].HasDirtyContext = TRUE;
> } else {
> SecondLevelPagingEntry = (VOID
> *)(UINTN)VTD_64BITS_ADDRESS(ExtContextEntry-
> >Bits.SecondLevelPageTranslationPointerLo, ExtContextEntry-
> >Bits.SecondLevelPageTranslationPointerHi);
> @@ -930,7 +1049,7 @@ SetAccessAttribute (
> }
> } else if (ContextEntry != NULL) {
> if (ContextEntry->Bits.Present == 0) {
> - SecondLevelPagingEntry = CreateSecondLevelPagingEntry (VtdIndex, 0);
> + SecondLevelPagingEntry = CreateSecondLevelPagingEntry (VtdIndex, 0,
> mVtdUnitInformation[VtdIndex].Is5LevelPaging);
> DEBUG ((DEBUG_VERBOSE,"SecondLevelPagingEntry - 0x%x (S%04x
> B%02x D%02x F%02x) New\n", SecondLevelPagingEntry, Segment,
> SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.Function));
> Pt = (UINT64)RShiftU64 ((UINT64)(UINTN)SecondLevelPagingEntry, 12);
>
> @@ -939,7 +1058,7 @@ SetAccessAttribute (
> ContextEntry->Bits.DomainIdentifier = DomainIdentifier;
> ContextEntry->Bits.Present = 1;
> FlushPageTableMemory (VtdIndex, (UINTN)ContextEntry,
> sizeof(*ContextEntry));
> - DumpDmarContextEntryTable
> (mVtdUnitInformation[VtdIndex].RootEntryTable);
> + DumpDmarContextEntryTable
> (mVtdUnitInformation[VtdIndex].RootEntryTable,
> mVtdUnitInformation[VtdIndex].Is5LevelPaging);
> mVtdUnitInformation[VtdIndex].HasDirtyContext = TRUE;
> } else {
> SecondLevelPagingEntry = (VOID
> *)(UINTN)VTD_64BITS_ADDRESS(ContextEntry-
> >Bits.SecondLevelPageTranslationPointerLo, ContextEntry-
> >Bits.SecondLevelPageTranslationPointerHi);
> @@ -1000,7 +1119,7 @@ AlwaysEnablePageAttribute (
>
> if (mVtdUnitInformation[VtdIndex].FixedSecondLevelPagingEntry == 0) {
> DEBUG((DEBUG_INFO, "CreateSecondLevelPagingEntry - %d\n",
> VtdIndex));
> - mVtdUnitInformation[VtdIndex].FixedSecondLevelPagingEntry =
> CreateSecondLevelPagingEntry (VtdIndex, EDKII_IOMMU_ACCESS_READ |
> EDKII_IOMMU_ACCESS_WRITE);
> + mVtdUnitInformation[VtdIndex].FixedSecondLevelPagingEntry =
> CreateSecondLevelPagingEntry (VtdIndex, EDKII_IOMMU_ACCESS_READ |
> EDKII_IOMMU_ACCESS_WRITE,
> mVtdUnitInformation[VtdIndex].Is5LevelPaging);
> }
>
> SecondLevelPagingEntry =
> mVtdUnitInformation[VtdIndex].FixedSecondLevelPagingEntry;
> diff --git
> a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTableEx.
> c
> b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTableEx.
> c
> index 0ed9e3ca..3918eeee 100644
> ---
> a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTableEx.
> c
> +++
> b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTableEx.
> c
> @@ -78,11 +78,32 @@ CreateExtContextEntry (
>
> DEBUG ((DEBUG_INFO,"DOMAIN: S%04x, B%02x D%02x F%02x\n",
> mVtdUnitInformation[VtdIndex].Segment, SourceId.Bits.Bus,
> SourceId.Bits.Device, SourceId.Bits.Function));
>
> - if ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW & BIT2) == 0) {
> - DEBUG((DEBUG_ERROR, "!!!! 4-level page-table is not supported on
> VTD %d !!!!\n", VtdIndex));
> + mVtdUnitInformation[VtdIndex].Is5LevelPaging = FALSE;
> + if ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW & BIT3) != 0) {
> + if ((PcdGet8(PcdVTdPolicyPropertyMask) & BIT3) != 0) {
> + DEBUG((DEBUG_ERROR, "Force to use 4-level page-table on VTD %d\n",
> VtdIndex));
> + ExtContextEntry->Bits.AddressWidth = 0x2;
> + } if ((PcdGet8(PcdVTdPolicyPropertyMask) & BIT4) != 0) {
> + DEBUG((DEBUG_ERROR, "Force to use 5-level page-table on VTD %d\n",
> VtdIndex));
> + ExtContextEntry->Bits.AddressWidth = 0x3;
> + mVtdUnitInformation[VtdIndex].Is5LevelPaging = TRUE;
> + } else {
> + if (mAcpiDmarTable->HostAddressWidth > 48) {
> + DEBUG((DEBUG_ERROR, "Using 5-level page-table on VTD %d\n",
> VtdIndex));
> + ExtContextEntry->Bits.AddressWidth = 0x3;
> + mVtdUnitInformation[VtdIndex].Is5LevelPaging = TRUE;
> + } else {
> + DEBUG((DEBUG_ERROR, "Using 4-level page-table on VTD %d\n",
> VtdIndex));
> + ExtContextEntry->Bits.AddressWidth = 0x2;
> + }
> + }
> + } else if ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW & BIT2) !=
> 0) {
> + DEBUG((DEBUG_ERROR, "Using 4-level page-table on VTD %d\n",
> VtdIndex));
> + ExtContextEntry->Bits.AddressWidth = 0x2;
> + } else {
> + DEBUG((DEBUG_ERROR, "!!!! Page-table type is not supported on
> VTD %d !!!!\n", VtdIndex));
> return EFI_UNSUPPORTED;
> }
> - ExtContextEntry->Bits.AddressWidth = 0x2;
> }
>
> FlushPageTableMemory (VtdIndex,
> (UINTN)mVtdUnitInformation[VtdIndex].ExtRootEntryTable,
> EFI_PAGES_TO_SIZE(EntryTablePages));
> @@ -93,11 +114,13 @@ CreateExtContextEntry (
> /**
> Dump DMAR extended context entry table.
>
> - @param[in] ExtRootEntry DMAR extended root entry.
> + @param[in] ExtRootEntry DMAR extended root entry.
> + @param[in] Is5LevelPaging If it is the 5 level paging.
> **/
> VOID
> DumpDmarExtContextEntryTable (
> - IN VTD_EXT_ROOT_ENTRY *ExtRootEntry
> + IN VTD_EXT_ROOT_ENTRY *ExtRootEntry,
> + IN BOOLEAN Is5LevelPaging
> )
> {
> UINTN Index;
> @@ -127,7 +150,7 @@ DumpDmarExtContextEntryTable (
> if (ExtContextEntry[Index2].Bits.Present == 0) {
> continue;
> }
> - DumpSecondLevelPagingEntry ((VOID
> *)(UINTN)VTD_64BITS_ADDRESS(ExtContextEntry[Index2].Bits.SecondLevelPa
> geTranslationPointerLo,
> ExtContextEntry[Index2].Bits.SecondLevelPageTranslationPointerHi));
> + DumpSecondLevelPagingEntry ((VOID
> *)(UINTN)VTD_64BITS_ADDRESS(ExtContextEntry[Index2].Bits.SecondLevelPa
> geTranslationPointerLo,
> ExtContextEntry[Index2].Bits.SecondLevelPageTranslationPointerHi),
> Is5LevelPaging);
> }
>
> if (ExtRootEntry[Index].Bits.UpperPresent == 0) {
> diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/VtdReg.c
> b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/VtdReg.c
> index 699639ba..686d235f 100644
> --- a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/VtdReg.c
> +++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/VtdReg.c
> @@ -174,8 +174,14 @@ PrepareVtdConfig (
> if ((mVtdUnitInformation[Index].CapReg.Bits.SLLPS & BIT0) == 0) {
> DEBUG((DEBUG_WARN, "!!!! 2MB super page is not supported on
> VTD %d !!!!\n", Index));
> }
> - if ((mVtdUnitInformation[Index].CapReg.Bits.SAGAW & BIT2) == 0) {
> - DEBUG((DEBUG_ERROR, "!!!! 4-level page-table is not supported on
> VTD %d !!!!\n", Index));
> + if ((mVtdUnitInformation[Index].CapReg.Bits.SAGAW & BIT3) != 0) {
> + DEBUG((DEBUG_INFO, "Support 5-level page-table on VTD %d\n",
> Index));
> + }
> + if ((mVtdUnitInformation[Index].CapReg.Bits.SAGAW & BIT2) != 0) {
> + DEBUG((DEBUG_INFO, "Support 4-level page-table on VTD %d\n",
> Index));
> + }
> + if ((mVtdUnitInformation[Index].CapReg.Bits.SAGAW & (BIT3 | BIT2)) == 0)
> {
> + DEBUG((DEBUG_ERROR, "!!!! Page-table type 0x%X is not supported on
> VTD %d !!!!\n", Index, mVtdUnitInformation[Index].CapReg.Bits.SAGAW));
> return ;
> }
>
> diff --git a/Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dec
> b/Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dec
> index 284820af..8f1edfe2 100644
> --- a/Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dec
> +++ b/Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dec
> @@ -95,6 +95,9 @@
> # BIT0: Enable IOMMU during boot (If DMAR table is installed in DXE. If
> VTD_INFO_PPI is installed in PEI.)
> # BIT1: Enable IOMMU when transfer control to OS (ExitBootService in
> normal boot. EndOfPEI in S3)
> # BIT2: Force no IOMMU access attribute request recording before DMAR
> table is installed.
> + # BIT3: Force to use 4 level paging.
> + # BIT4: If iommu support 5 level paging, force to use 5 level paging.
> + # (If both BIT3 and BIT4 are set, force to use 4 level paging.)
> # @Prompt The policy for VTd driver behavior.
>
> gIntelSiliconPkgTokenSpaceGuid.PcdVTdPolicyPropertyMask|1|UINT8|0x000
> 00002
>
> --
> 2.16.2.windows.1
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v3] IntelSiliconPkg/VTd: Add iommu 5 level paging support
2020-11-18 1:39 ` Yao, Jiewen
@ 2020-11-18 2:33 ` Sheng Wei
2020-11-18 2:49 ` Yao, Jiewen
[not found] ` <16487A52A9CBAF90.960@groups.io>
0 siblings, 2 replies; 6+ messages in thread
From: Sheng Wei @ 2020-11-18 2:33 UTC (permalink / raw)
To: Yao, Jiewen, devel@edk2.groups.io
Cc: Ni, Ray, Chaganty, Rangasai V, Huang, Jenny
[-- Attachment #1: Type: text/plain, Size: 44132 bytes --]
Hi Jeiwen,
For comment 1:
The code about (SAGAW & BIT2) is just behand (SAGAW & BIT3)
> > + DEBUG((DEBUG_ERROR, "Using 4-level page-table on VTD %d\n",
> > VtdIndex));
> > + ExtContextEntry->Bits.AddressWidth = 0x2;
> > + }
> > + }
> > + } else if ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW &
> > + BIT2) !=
> > 0) {
> > + DEBUG((DEBUG_ERROR, "Using 4-level page-table on VTD %d\n",
> > VtdIndex));
> > + ExtContextEntry->Bits.AddressWidth = 0x2;
> > + } else {
> > + DEBUG((DEBUG_ERROR, "!!!! Page-table type is not supported on
> > VTD %d !!!!\n", VtdIndex));
> > return EFI_UNSUPPORTED;
> > }
> > - ExtContextEntry->Bits.AddressWidth = 0x2;
> > }
For comment 2:
> # BIT3: Force to use 4 level paging.
> # BIT4: If iommu support 5 level paging, force to use 5 level paging.
> # (If both BIT3 and BIT4 are set, force to use 4 level paging.)
Mostly, these 2 bits are for debug/test purpose, it could be used to force the page table depth.
Do you think it is no necessary? Or we could find another solution ?
Thank you
BR
Sheng Wei
> -----Original Message-----
> From: Yao, Jiewen <jiewen.yao@intel.com>
> Sent: 2020年11月18日 9:39
> To: Sheng, W <w.sheng@intel.com>; devel@edk2.groups.io
> Cc: Ni, Ray <ray.ni@intel.com>; Chaganty, Rangasai V
> <rangasai.v.chaganty@intel.com>; Huang, Jenny <jenny.huang@intel.com>
> Subject: RE: [PATCH v3] IntelSiliconPkg/VTd: Add iommu 5 level paging support
>
> Hi
> I have 2 comments:
>
> 1) below capability check seems not correct.
>
> (SAGAW & BIT3) is for 5 level only.
> We need check (SAGAW & BIT2) for 4 level. But I do not see the code. Do I miss
> something?
>
> if ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW & BIT3) != 0) {
> if ((PcdGet8(PcdVTdPolicyPropertyMask) & BIT3) != 0) {
> DEBUG((DEBUG_ERROR, "Force to use 4-level page-table on VTD %d\n",
> VtdIndex));
> ContextEntry->Bits.AddressWidth = 0x2;
> } if ((PcdGet8(PcdVTdPolicyPropertyMask) & BIT4) != 0) {
> DEBUG((DEBUG_ERROR, "Force to use 5-level page-table on VTD %d\n",
> VtdIndex));
> ContextEntry->Bits.AddressWidth = 0x3;
> mVtdUnitInformation[VtdIndex].Is5LevelPaging = TRUE;
> } else {
> if (mAcpiDmarTable->HostAddressWidth > 48) {
> DEBUG((DEBUG_ERROR, "Using 5-level page-table on VTD %d\n",
> VtdIndex));
> ContextEntry->Bits.AddressWidth = 0x3;
> mVtdUnitInformation[VtdIndex].Is5LevelPaging = TRUE;
> } else {
> DEBUG((DEBUG_ERROR, "Using 4-level page-table on VTD %d\n",
> VtdIndex));
> ContextEntry->Bits.AddressWidth = 0x2;
> }
> }
>
> 2) I am wondering, do we really need 2 bit for level selection ?
> What if force 4 level, but the platform does not support?
> What if force 5 level, but the platform does not support?
>
> # BIT3: Force to use 4 level paging.
> # BIT4: If iommu support 5 level paging, force to use 5 level paging.
> # (If both BIT3 and BIT4 are set, force to use 4 level paging.)
>
> gIntelSiliconPkgTokenSpaceGuid.PcdVTdPolicyPropertyMask|1|UINT8|0x00000
> 002
>
> Can we align the solution in DXE/SMM paging solution?
>
>
>
> > -----Original Message-----
> > From: Sheng, W <w.sheng@intel.com>
> > Sent: Wednesday, November 18, 2020 9:18 AM
> > To: devel@edk2.groups.io
> > Cc: Ni, Ray <ray.ni@intel.com>; Chaganty, Rangasai V
> > <rangasai.v.chaganty@intel.com>; Yao, Jiewen <jiewen.yao@intel.com>;
> > Huang, Jenny <jenny.huang@intel.com>
> > Subject: [PATCH v3] IntelSiliconPkg/VTd: Add iommu 5 level paging
> > support
> >
> > Support iommu 5 level paging for translation table.
> >
> > REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3067
> >
> > 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: Jiewen Yao <jiewen.yao@intel.com>
> > Cc: Jenny Huang <jenny.huang@intel.com>
> > ---
> > .../Feature/VTd/IntelVTdDxe/DmaProtection.c | 4 +-
> > .../Feature/VTd/IntelVTdDxe/DmaProtection.h | 19 +-
> > .../Feature/VTd/IntelVTdDxe/TranslationTable.c | 287 +++++++++++++++--
> > ----
> > .../Feature/VTd/IntelVTdDxe/TranslationTableEx.c | 35 ++-
> > .../Feature/VTd/IntelVTdDxe/VtdReg.c | 10 +-
> > Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dec | 3 +
> > 6 files changed, 258 insertions(+), 100 deletions(-)
> >
> > diff --git
> > a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.
> > c
> > b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.
> > c
> > index 9b6135ef..628565ee 100644
> > ---
> > a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.
> > c
> > +++
> > b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.
> > c
> > @@ -523,10 +523,10 @@ SetupVtd (
> > for (Index = 0; Index < mVtdUnitNumber; Index++) {
> > DEBUG ((DEBUG_INFO,"VTD Unit %d (Segment: %04x)\n", Index,
> > mVtdUnitInformation[Index].Segment));
> > if (mVtdUnitInformation[Index].ExtRootEntryTable != NULL) {
> > - DumpDmarExtContextEntryTable
> > (mVtdUnitInformation[Index].ExtRootEntryTable);
> > + DumpDmarExtContextEntryTable
> > (mVtdUnitInformation[Index].ExtRootEntryTable,
> > mVtdUnitInformation[Index].Is5LevelPaging);
> > }
> > if (mVtdUnitInformation[Index].RootEntryTable != NULL) {
> > - DumpDmarContextEntryTable
> > (mVtdUnitInformation[Index].RootEntryTable);
> > + DumpDmarContextEntryTable
> > (mVtdUnitInformation[Index].RootEntryTable,
> > mVtdUnitInformation[Index].Is5LevelPaging);
> > }
> > }
> >
> > diff --git
> > a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.
> > h
> > b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.
> > h
> > index a3331db8..f641cea0 100644
> > ---
> > a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.
> > h
> > +++
> > b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.
> > h
> > @@ -77,6 +77,7 @@ typedef struct {
> > BOOLEAN HasDirtyContext;
> > BOOLEAN HasDirtyPages;
> > PCI_DEVICE_INFORMATION PciDeviceInfo;
> > + BOOLEAN Is5LevelPaging;
> > } VTD_UNIT_INFORMATION;
> >
> > //
> > @@ -375,31 +376,37 @@ ParseDmarAcpiTableRmrr (
> > /**
> > Dump DMAR context entry table.
> >
> > - @param[in] RootEntry DMAR root entry.
> > + @param[in] RootEntry DMAR root entry.
> > + @param[in] Is5LevelPaging If it is the 5 level paging.
> > **/
> > VOID
> > DumpDmarContextEntryTable (
> > - IN VTD_ROOT_ENTRY *RootEntry
> > + IN VTD_ROOT_ENTRY *RootEntry,
> > + IN BOOLEAN Is5LevelPaging
> > );
> >
> > /**
> > Dump DMAR extended context entry table.
> >
> > - @param[in] ExtRootEntry DMAR extended root entry.
> > + @param[in] ExtRootEntry DMAR extended root entry.
> > + @param[in] Is5LevelPaging If it is the 5 level paging.
> > **/
> > VOID
> > DumpDmarExtContextEntryTable (
> > - IN VTD_EXT_ROOT_ENTRY *ExtRootEntry
> > + IN VTD_EXT_ROOT_ENTRY *ExtRootEntry, IN BOOLEAN Is5LevelPaging
> > );
> >
> > /**
> > Dump DMAR second level paging entry.
> >
> > - @param[in] SecondLevelPagingEntry The second level paging entry.
> > + @param[in] SecondLevelPagingEntry The second level paging entry.
> > + @param[in] Is5LevelPaging If it is the 5 level paging.
> > **/
> > VOID
> > DumpSecondLevelPagingEntry (
> > - IN VOID *SecondLevelPagingEntry
> > + IN VOID *SecondLevelPagingEntry,
> > + IN BOOLEAN Is5LevelPaging
> > );
> >
> > /**
> > diff --git
> > a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTab
> > le.c
> > b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTab
> > le.c
> > index 201d663d..cb59860a 100644
> > ---
> > a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTab
> > le.c
> > +++
> > b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTab
> > le.c @@ -128,11 +128,32 @@ CreateContextEntry (
> >
> > DEBUG ((DEBUG_INFO,"Source: S%04x B%02x D%02x F%02x\n",
> > mVtdUnitInformation[VtdIndex].Segment, SourceId.Bits.Bus,
> > SourceId.Bits.Device, SourceId.Bits.Function));
> >
> > - if ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW & BIT2) == 0) {
> > - DEBUG((DEBUG_ERROR, "!!!! 4-level page-table is not supported on
> > VTD %d !!!!\n", VtdIndex));
> > + mVtdUnitInformation[VtdIndex].Is5LevelPaging = FALSE;
> > + if ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW & BIT3) != 0) {
> > + if ((PcdGet8(PcdVTdPolicyPropertyMask) & BIT3) != 0) {
> > + DEBUG((DEBUG_ERROR, "Force to use 4-level page-table on VTD
> > + %d\n",
> > VtdIndex));
> > + ContextEntry->Bits.AddressWidth = 0x2;
> > + } if ((PcdGet8(PcdVTdPolicyPropertyMask) & BIT4) != 0) {
> > + DEBUG((DEBUG_ERROR, "Force to use 5-level page-table on VTD
> > + %d\n",
> > VtdIndex));
> > + ContextEntry->Bits.AddressWidth = 0x3;
> > + mVtdUnitInformation[VtdIndex].Is5LevelPaging = TRUE;
> > + } else {
> > + if (mAcpiDmarTable->HostAddressWidth > 48) {
> > + DEBUG((DEBUG_ERROR, "Using 5-level page-table on VTD %d\n",
> > VtdIndex));
> > + ContextEntry->Bits.AddressWidth = 0x3;
> > + mVtdUnitInformation[VtdIndex].Is5LevelPaging = TRUE;
> > + } else {
> > + DEBUG((DEBUG_ERROR, "Using 4-level page-table on VTD %d\n",
> > VtdIndex));
> > + ContextEntry->Bits.AddressWidth = 0x2;
> > + }
> > + }
> > + } else if ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW &
> > + BIT2) !=
> > 0) {
> > + DEBUG((DEBUG_ERROR, "Using 4-level page-table on VTD %d\n",
> > VtdIndex));
> > + ContextEntry->Bits.AddressWidth = 0x2;
> > + } else {
> > + DEBUG((DEBUG_ERROR, "!!!! Page-table type is not supported on
> > VTD %d !!!!\n", VtdIndex));
> > return EFI_UNSUPPORTED;
> > }
> > - ContextEntry->Bits.AddressWidth = 0x2;
> > }
> >
> > FlushPageTableMemory (VtdIndex,
> > (UINTN)mVtdUnitInformation[VtdIndex].RootEntryTable,
> > EFI_PAGES_TO_SIZE(EntryTablePages));
> > @@ -148,6 +169,7 @@ CreateContextEntry (
> > @param[in] MemoryBase The base of the memory.
> > @param[in] MemoryLimit The limit of the memory.
> > @param[in] IoMmuAccess The IOMMU access.
> > + @param[in] Is5LevelPaging If it is the 5 level paging.
> >
> > @return The second level paging entry.
> > **/
> > @@ -157,16 +179,23 @@ CreateSecondLevelPagingEntryTable (
> > IN VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry,
> > IN UINT64 MemoryBase,
> > IN UINT64 MemoryLimit,
> > - IN UINT64 IoMmuAccess
> > + IN UINT64 IoMmuAccess,
> > + IN BOOLEAN Is5LevelPaging
> > )
> > {
> > + UINTN Index5;
> > UINTN Index4;
> > UINTN Index3;
> > UINTN Index2;
> > + UINTN Lvl5Start;
> > + UINTN Lvl5End;
> > + UINTN Lvl4PagesStart;
> > + UINTN Lvl4PagesEnd;
> > UINTN Lvl4Start;
> > UINTN Lvl4End;
> > UINTN Lvl3Start;
> > UINTN Lvl3End;
> > + VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl5PtEntry;
> > VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl4PtEntry;
> > VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl3PtEntry;
> > VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl2PtEntry; @@ -184,7 +213,7
> @@
> > CreateSecondLevelPagingEntryTable (
> > if (SecondLevelPagingEntry == NULL) {
> > SecondLevelPagingEntry = AllocateZeroPages (1);
> > if (SecondLevelPagingEntry == NULL) {
> > - DEBUG ((DEBUG_ERROR,"Could not Alloc LVL4 PT. \n"));
> > + DEBUG ((DEBUG_ERROR,"Could not Alloc LVL4 or LVL5 PT. \n"));
> > return NULL;
> > }
> > FlushPageTableMemory (VtdIndex, (UINTN)SecondLevelPagingEntry,
> > EFI_PAGES_TO_SIZE(1)); @@ -197,66 +226,109 @@
> > CreateSecondLevelPagingEntryTable (
> > return SecondLevelPagingEntry;
> > }
> >
> > - Lvl4Start = RShiftU64 (BaseAddress, 39) & 0x1FF;
> > - Lvl4End = RShiftU64 (EndAddress - 1, 39) & 0x1FF;
> > + if (Is5LevelPaging) {
> > + Lvl5Start = RShiftU64 (BaseAddress, 48) & 0x1FF;
> > + Lvl5End = RShiftU64 (EndAddress - 1, 48) & 0x1FF;
> > + DEBUG ((DEBUG_INFO," Lvl5Start - 0x%x, Lvl5End - 0x%x\n",
> > + Lvl5Start,
> > Lvl5End));
> >
> > - DEBUG ((DEBUG_INFO," Lvl4Start - 0x%x, Lvl4End - 0x%x\n",
> > Lvl4Start, Lvl4End));
> > + Lvl4Start = RShiftU64 (BaseAddress, 39) & 0x1FF;
> > + Lvl4End = RShiftU64 (EndAddress - 1, 39) & 0x1FF;
> >
> > - Lvl4PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> > *)SecondLevelPagingEntry;
> > - for (Index4 = Lvl4Start; Index4 <= Lvl4End; Index4++) {
> > - if (Lvl4PtEntry[Index4].Uint64 == 0) {
> > - Lvl4PtEntry[Index4].Uint64 = (UINT64)(UINTN)AllocateZeroPages (1);
> > - if (Lvl4PtEntry[Index4].Uint64 == 0) {
> > - DEBUG ((DEBUG_ERROR,"!!!!!! ALLOCATE LVL4 PAGE FAIL
> > (0x%x)!!!!!!\n", Index4));
> > - ASSERT(FALSE);
> > - return NULL;
> > - }
> > - FlushPageTableMemory (VtdIndex, (UINTN)Lvl4PtEntry[Index4].Uint64,
> > SIZE_4KB);
> > - SetSecondLevelPagingEntryAttribute (&Lvl4PtEntry[Index4],
> > EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);
> > - }
> > + Lvl4PagesStart = (Lvl5Start<<9) | Lvl4Start;
> > + Lvl4PagesEnd = (Lvl5End<<9) | Lvl4End;
> > + DEBUG ((DEBUG_INFO," Lvl4PagesStart - 0x%x, Lvl4PagesEnd -
> > + 0x%x\n",
> > Lvl4PagesStart, Lvl4PagesEnd));
> >
> > - Lvl3Start = RShiftU64 (BaseAddress, 30) & 0x1FF;
> > - if (ALIGN_VALUE_LOW(BaseAddress + SIZE_1GB, SIZE_1GB) <=
> > EndAddress) {
> > - Lvl3End = SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY) - 1;
> > - } else {
> > - Lvl3End = RShiftU64 (EndAddress - 1, 30) & 0x1FF;
> > + Lvl5PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> > *)SecondLevelPagingEntry;
> > + } else {
> > + Lvl5Start = RShiftU64 (BaseAddress, 48) & 0x1FF;
> > + Lvl5End = Lvl5Start;
> > +
> > + Lvl4Start = RShiftU64 (BaseAddress, 39) & 0x1FF;
> > + Lvl4End = RShiftU64 (EndAddress - 1, 39) & 0x1FF;
> > + DEBUG ((DEBUG_INFO," Lvl4Start - 0x%x, Lvl4End - 0x%x\n",
> > + Lvl4Start,
> > Lvl4End));
> > +
> > + Lvl4PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> > *)SecondLevelPagingEntry;
> > + }
> > +
> > + for (Index5 = Lvl5Start; Index5 <= Lvl5End; Index5++) {
> > + if (Is5LevelPaging) {
> > + if (Lvl5PtEntry[Index5].Uint64 == 0) {
> > + Lvl5PtEntry[Index5].Uint64 = (UINT64)(UINTN)AllocateZeroPages (1);
> > + if (Lvl5PtEntry[Index5].Uint64 == 0) {
> > + DEBUG ((DEBUG_ERROR,"!!!!!! ALLOCATE LVL4 PAGE FAIL
> > (0x%x)!!!!!!\n", Index5));
> > + ASSERT(FALSE);
> > + return NULL;
> > + }
> > + FlushPageTableMemory (VtdIndex,
> > + (UINTN)Lvl5PtEntry[Index5].Uint64,
> > SIZE_4KB);
> > + SetSecondLevelPagingEntryAttribute (&Lvl5PtEntry[Index5],
> > EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);
> > + }
> > + Lvl4Start = Lvl4PagesStart & 0x1FF;
> > + if (((Index5+1)<<9) > Lvl4PagesEnd) {
> > + Lvl4End = SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY) - 1;;
> > + Lvl4PagesStart = (Index5+1)<<9;
> > + } else {
> > + Lvl4End = Lvl4PagesEnd & 0x1FF;
> > + }
> > + DEBUG ((DEBUG_INFO," Lvl5(0x%x): Lvl4Start - 0x%x, Lvl4End -
> > + 0x%x\n",
> > Index5, Lvl4Start, Lvl4End));
> > + Lvl4PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> > *)(UINTN)VTD_64BITS_ADDRESS(Lvl5PtEntry[Index5].Bits.AddressLo,
> > Lvl5PtEntry[Index5].Bits.AddressHi);
> > }
> > - DEBUG ((DEBUG_INFO," Lvl4(0x%x): Lvl3Start - 0x%x, Lvl3End - 0x%x\n",
> > Index4, Lvl3Start, Lvl3End));
> >
> > - Lvl3PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> > *)(UINTN)VTD_64BITS_ADDRESS(Lvl4PtEntry[Index4].Bits.AddressLo,
> > Lvl4PtEntry[Index4].Bits.AddressHi);
> > - for (Index3 = Lvl3Start; Index3 <= Lvl3End; Index3++) {
> > - if (Lvl3PtEntry[Index3].Uint64 == 0) {
> > - Lvl3PtEntry[Index3].Uint64 = (UINT64)(UINTN)AllocateZeroPages (1);
> > - if (Lvl3PtEntry[Index3].Uint64 == 0) {
> > - DEBUG ((DEBUG_ERROR,"!!!!!! ALLOCATE LVL3 PAGE FAIL (0x%x,
> > 0x%x)!!!!!!\n", Index4, Index3));
> > + for (Index4 = Lvl4Start; Index4 <= Lvl4End; Index4++) {
> > + if (Lvl4PtEntry[Index4].Uint64 == 0) {
> > + Lvl4PtEntry[Index4].Uint64 = (UINT64)(UINTN)AllocateZeroPages (1);
> > + if (Lvl4PtEntry[Index4].Uint64 == 0) {
> > + DEBUG ((DEBUG_ERROR,"!!!!!! ALLOCATE LVL4 PAGE FAIL
> > (0x%x)!!!!!!\n", Index4));
> > ASSERT(FALSE);
> > return NULL;
> > }
> > - FlushPageTableMemory (VtdIndex, (UINTN)Lvl3PtEntry[Index3].Uint64,
> > SIZE_4KB);
> > - SetSecondLevelPagingEntryAttribute (&Lvl3PtEntry[Index3],
> > EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);
> > + FlushPageTableMemory (VtdIndex,
> > + (UINTN)Lvl4PtEntry[Index4].Uint64,
> > SIZE_4KB);
> > + SetSecondLevelPagingEntryAttribute (&Lvl4PtEntry[Index4],
> > EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);
> > }
> >
> > - Lvl2PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> > *)(UINTN)VTD_64BITS_ADDRESS(Lvl3PtEntry[Index3].Bits.AddressLo,
> > Lvl3PtEntry[Index3].Bits.AddressHi);
> > - for (Index2 = 0; Index2 <
> > SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY); Index2++) {
> > - Lvl2PtEntry[Index2].Uint64 = BaseAddress;
> > - SetSecondLevelPagingEntryAttribute (&Lvl2PtEntry[Index2],
> > IoMmuAccess);
> > - Lvl2PtEntry[Index2].Bits.PageSize = 1;
> > - BaseAddress += SIZE_2MB;
> > + Lvl3Start = RShiftU64 (BaseAddress, 30) & 0x1FF;
> > + if (ALIGN_VALUE_LOW(BaseAddress + SIZE_1GB, SIZE_1GB) <=
> > EndAddress) {
> > + Lvl3End = SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY) - 1;
> > + } else {
> > + Lvl3End = RShiftU64 (EndAddress - 1, 30) & 0x1FF;
> > + }
> > + DEBUG ((DEBUG_INFO," Lvl4(0x%x): Lvl3Start - 0x%x, Lvl3End -
> > + 0x%x\n",
> > Index4, Lvl3Start, Lvl3End));
> > +
> > + Lvl3PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> > *)(UINTN)VTD_64BITS_ADDRESS(Lvl4PtEntry[Index4].Bits.AddressLo,
> > Lvl4PtEntry[Index4].Bits.AddressHi);
> > + for (Index3 = Lvl3Start; Index3 <= Lvl3End; Index3++) {
> > + if (Lvl3PtEntry[Index3].Uint64 == 0) {
> > + Lvl3PtEntry[Index3].Uint64 = (UINT64)(UINTN)AllocateZeroPages (1);
> > + if (Lvl3PtEntry[Index3].Uint64 == 0) {
> > + DEBUG ((DEBUG_ERROR,"!!!!!! ALLOCATE LVL3 PAGE FAIL
> > + (0x%x,
> > 0x%x)!!!!!!\n", Index4, Index3));
> > + ASSERT(FALSE);
> > + return NULL;
> > + }
> > + FlushPageTableMemory (VtdIndex,
> > + (UINTN)Lvl3PtEntry[Index3].Uint64,
> > SIZE_4KB);
> > + SetSecondLevelPagingEntryAttribute (&Lvl3PtEntry[Index3],
> > EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);
> > + }
> > +
> > + Lvl2PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> > *)(UINTN)VTD_64BITS_ADDRESS(Lvl3PtEntry[Index3].Bits.AddressLo,
> > Lvl3PtEntry[Index3].Bits.AddressHi);
> > + for (Index2 = 0; Index2 <
> > SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY); Index2++) {
> > + Lvl2PtEntry[Index2].Uint64 = BaseAddress;
> > + SetSecondLevelPagingEntryAttribute (&Lvl2PtEntry[Index2],
> > IoMmuAccess);
> > + Lvl2PtEntry[Index2].Bits.PageSize = 1;
> > + BaseAddress += SIZE_2MB;
> > + if (BaseAddress >= MemoryLimit) {
> > + break;
> > + }
> > + }
> > + FlushPageTableMemory (VtdIndex, (UINTN)Lvl2PtEntry,
> > + SIZE_4KB);
> > if (BaseAddress >= MemoryLimit) {
> > break;
> > }
> > }
> > - FlushPageTableMemory (VtdIndex, (UINTN)Lvl2PtEntry, SIZE_4KB);
> > + FlushPageTableMemory (VtdIndex, (UINTN)&Lvl3PtEntry[Lvl3Start],
> > (UINTN)&Lvl3PtEntry[Lvl3End + 1] - (UINTN)&Lvl3PtEntry[Lvl3Start]);
> > if (BaseAddress >= MemoryLimit) {
> > break;
> > }
> > }
> > - FlushPageTableMemory (VtdIndex, (UINTN)&Lvl3PtEntry[Lvl3Start],
> > (UINTN)&Lvl3PtEntry[Lvl3End + 1] - (UINTN)&Lvl3PtEntry[Lvl3Start]);
> > - if (BaseAddress >= MemoryLimit) {
> > - break;
> > - }
> > + FlushPageTableMemory (VtdIndex, (UINTN)&Lvl4PtEntry[Lvl4Start],
> > (UINTN)&Lvl4PtEntry[Lvl4End + 1] - (UINTN)&Lvl4PtEntry[Lvl4Start]);
> > }
> > - FlushPageTableMemory (VtdIndex, (UINTN)&Lvl4PtEntry[Lvl4Start],
> > (UINTN)&Lvl4PtEntry[Lvl4End + 1] - (UINTN)&Lvl4PtEntry[Lvl4Start]);
> > + FlushPageTableMemory (VtdIndex, (UINTN)&Lvl5PtEntry[Lvl5Start],
> > (UINTN)&Lvl5PtEntry[Lvl5End + 1] - (UINTN)&Lvl5PtEntry[Lvl5Start]);
> >
> > return SecondLevelPagingEntry;
> > }
> > @@ -266,26 +338,28 @@ CreateSecondLevelPagingEntryTable (
> >
> > @param[in] VtdIndex The index of the VTd engine.
> > @param[in] IoMmuAccess The IOMMU access.
> > + @param[in] Is5LevelPaging If it is the 5 level paging.
> >
> > @return The second level paging entry.
> > **/
> > VTD_SECOND_LEVEL_PAGING_ENTRY *
> > CreateSecondLevelPagingEntry (
> > IN UINTN VtdIndex,
> > - IN UINT64 IoMmuAccess
> > + IN UINT64 IoMmuAccess,
> > + IN BOOLEAN Is5LevelPaging
> > )
> > {
> > VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry;
> >
> > SecondLevelPagingEntry = NULL;
> > - SecondLevelPagingEntry = CreateSecondLevelPagingEntryTable
> > (VtdIndex, SecondLevelPagingEntry, 0, mBelow4GMemoryLimit,
> > IoMmuAccess);
> > + SecondLevelPagingEntry = CreateSecondLevelPagingEntryTable
> > + (VtdIndex,
> > SecondLevelPagingEntry, 0, mBelow4GMemoryLimit, IoMmuAccess,
> > Is5LevelPaging);
> > if (SecondLevelPagingEntry == NULL) {
> > return NULL;
> > }
> >
> > if (mAbove4GMemoryLimit != 0) {
> > ASSERT (mAbove4GMemoryLimit > BASE_4GB);
> > - SecondLevelPagingEntry = CreateSecondLevelPagingEntryTable (VtdIndex,
> > SecondLevelPagingEntry, SIZE_4GB, mAbove4GMemoryLimit, IoMmuAccess);
> > + SecondLevelPagingEntry = CreateSecondLevelPagingEntryTable
> > + (VtdIndex,
> > SecondLevelPagingEntry, SIZE_4GB, mAbove4GMemoryLimit, IoMmuAccess,
> > Is5LevelPaging);
> > if (SecondLevelPagingEntry == NULL) {
> > return NULL;
> > }
> > @@ -326,11 +400,13 @@ SetupTranslationTable (
> > /**
> > Dump DMAR context entry table.
> >
> > - @param[in] RootEntry DMAR root entry.
> > + @param[in] RootEntry DMAR root entry.
> > + @param[in] Is5LevelPaging If it is the 5 level paging.
> > **/
> > VOID
> > DumpDmarContextEntryTable (
> > - IN VTD_ROOT_ENTRY *RootEntry
> > + IN VTD_ROOT_ENTRY *RootEntry,
> > + IN BOOLEAN Is5LevelPaging
> > )
> > {
> > UINTN Index;
> > @@ -359,7 +435,7 @@ DumpDmarContextEntryTable (
> > if (ContextEntry[Index2].Bits.Present == 0) {
> > continue;
> > }
> > - DumpSecondLevelPagingEntry ((VOID
> > *)(UINTN)VTD_64BITS_ADDRESS(ContextEntry[Index2].Bits.SecondLevelPage
> > TranslationPointerLo,
> > ContextEntry[Index2].Bits.SecondLevelPageTranslationPointerHi));
> > + DumpSecondLevelPagingEntry ((VOID
> > *)(UINTN)VTD_64BITS_ADDRESS(ContextEntry[Index2].Bits.SecondLevelPage
> > TranslationPointerLo,
> > ContextEntry[Index2].Bits.SecondLevelPageTranslationPointerHi),
> > Is5LevelPaging);
> > }
> > }
> > DEBUG ((DEBUG_INFO,"=========================\n"));
> > @@ -368,17 +444,22 @@ DumpDmarContextEntryTable (
> > /**
> > Dump DMAR second level paging entry.
> >
> > - @param[in] SecondLevelPagingEntry The second level paging entry.
> > + @param[in] SecondLevelPagingEntry The second level paging entry.
> > + @param[in] Is5LevelPaging If it is the 5 level paging.
> > **/
> > VOID
> > DumpSecondLevelPagingEntry (
> > - IN VOID *SecondLevelPagingEntry
> > + IN VOID *SecondLevelPagingEntry,
> > + IN BOOLEAN Is5LevelPaging
> > )
> > {
> > + UINTN Index5;
> > UINTN Index4;
> > UINTN Index3;
> > UINTN Index2;
> > UINTN Index1;
> > + UINTN Lvl5IndexEnd;
> > + VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl5PtEntry;
> > VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl4PtEntry;
> > VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl3PtEntry;
> > VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl2PtEntry; @@ -386,38 +467,53
> @@
> > DumpSecondLevelPagingEntry (
> >
> > DEBUG ((DEBUG_VERBOSE,"================\n"));
> > DEBUG ((DEBUG_VERBOSE,"DMAR Second Level Page Table:\n"));
> > + DEBUG ((DEBUG_VERBOSE,"SecondLevelPagingEntry Base - 0x%x,
> > Is5LevelPaging - %d\n", SecondLevelPagingEntry, Is5LevelPaging));
> >
> > - DEBUG ((DEBUG_VERBOSE,"SecondLevelPagingEntry Base - 0x%x\n",
> > SecondLevelPagingEntry));
> > + Lvl5IndexEnd = Is5LevelPaging ?
> > SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY) : 1;
> > Lvl4PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> > *)SecondLevelPagingEntry;
> > - for (Index4 = 0; Index4 <
> > SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY); Index4++) {
> > - if (Lvl4PtEntry[Index4].Uint64 != 0) {
> > - DEBUG ((DEBUG_VERBOSE," Lvl4Pt Entry(0x%03x) - 0x%016lx\n", Index4,
> > Lvl4PtEntry[Index4].Uint64));
> > - }
> > - if (Lvl4PtEntry[Index4].Uint64 == 0) {
> > - continue;
> > - }
> > - Lvl3PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> > *)(UINTN)VTD_64BITS_ADDRESS(Lvl4PtEntry[Index4].Bits.AddressLo,
> > Lvl4PtEntry[Index4].Bits.AddressHi);
> > - for (Index3 = 0; Index3 <
> > SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY); Index3++) {
> > - if (Lvl3PtEntry[Index3].Uint64 != 0) {
> > - DEBUG ((DEBUG_VERBOSE," Lvl3Pt Entry(0x%03x) - 0x%016lx\n",
> > Index3, Lvl3PtEntry[Index3].Uint64));
> > + Lvl5PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> > *)SecondLevelPagingEntry;
> > +
> > + for (Index5 = 0; Index5 < Lvl5IndexEnd; Index5++) {
> > + if (Is5LevelPaging) {
> > + if (Lvl5PtEntry[Index5].Uint64 != 0) {
> > + DEBUG ((DEBUG_VERBOSE," Lvl5Pt Entry(0x%03x) - 0x%016lx\n",
> > Index5, Lvl5PtEntry[Index5].Uint64));
> > }
> > - if (Lvl3PtEntry[Index3].Uint64 == 0) {
> > + if (Lvl5PtEntry[Index5].Uint64 == 0) {
> > continue;
> > }
> > + Lvl4PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> > *)(UINTN)VTD_64BITS_ADDRESS(Lvl5PtEntry[Index5].Bits.AddressLo,
> > Lvl5PtEntry[Index5].Bits.AddressHi);
> > + }
> >
> > - Lvl2PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> > *)(UINTN)VTD_64BITS_ADDRESS(Lvl3PtEntry[Index3].Bits.AddressLo,
> > Lvl3PtEntry[Index3].Bits.AddressHi);
> > - for (Index2 = 0; Index2 <
> > SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY); Index2++) {
> > - if (Lvl2PtEntry[Index2].Uint64 != 0) {
> > - DEBUG ((DEBUG_VERBOSE," Lvl2Pt Entry(0x%03x) - 0x%016lx\n",
> > Index2, Lvl2PtEntry[Index2].Uint64));
> > + for (Index4 = 0; Index4 <
> > SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY); Index4++) {
> > + if (Lvl4PtEntry[Index4].Uint64 != 0) {
> > + DEBUG ((DEBUG_VERBOSE," Lvl4Pt Entry(0x%03x) - 0x%016lx\n",
> > Index4, Lvl4PtEntry[Index4].Uint64));
> > + }
> > + if (Lvl4PtEntry[Index4].Uint64 == 0) {
> > + continue;
> > + }
> > + Lvl3PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> > *)(UINTN)VTD_64BITS_ADDRESS(Lvl4PtEntry[Index4].Bits.AddressLo,
> > Lvl4PtEntry[Index4].Bits.AddressHi);
> > + for (Index3 = 0; Index3 <
> > SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY); Index3++) {
> > + if (Lvl3PtEntry[Index3].Uint64 != 0) {
> > + DEBUG ((DEBUG_VERBOSE," Lvl3Pt Entry(0x%03x) - 0x%016lx\n",
> > Index3, Lvl3PtEntry[Index3].Uint64));
> > }
> > - if (Lvl2PtEntry[Index2].Uint64 == 0) {
> > + if (Lvl3PtEntry[Index3].Uint64 == 0) {
> > continue;
> > }
> > - if (Lvl2PtEntry[Index2].Bits.PageSize == 0) {
> > - Lvl1PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> > *)(UINTN)VTD_64BITS_ADDRESS(Lvl2PtEntry[Index2].Bits.AddressLo,
> > Lvl2PtEntry[Index2].Bits.AddressHi);
> > - for (Index1 = 0; Index1 <
> > SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY); Index1++) {
> > - if (Lvl1PtEntry[Index1].Uint64 != 0) {
> > - DEBUG ((DEBUG_VERBOSE," Lvl1Pt Entry(0x%03x) -
> 0x%016lx\n",
> > Index1, Lvl1PtEntry[Index1].Uint64));
> > +
> > + Lvl2PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> > *)(UINTN)VTD_64BITS_ADDRESS(Lvl3PtEntry[Index3].Bits.AddressLo,
> > Lvl3PtEntry[Index3].Bits.AddressHi);
> > + for (Index2 = 0; Index2 <
> > SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY); Index2++) {
> > + if (Lvl2PtEntry[Index2].Uint64 != 0) {
> > + DEBUG ((DEBUG_VERBOSE," Lvl2Pt Entry(0x%03x) - 0x%016lx\n",
> > Index2, Lvl2PtEntry[Index2].Uint64));
> > + }
> > + if (Lvl2PtEntry[Index2].Uint64 == 0) {
> > + continue;
> > + }
> > + if (Lvl2PtEntry[Index2].Bits.PageSize == 0) {
> > + Lvl1PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> > *)(UINTN)VTD_64BITS_ADDRESS(Lvl2PtEntry[Index2].Bits.AddressLo,
> > Lvl2PtEntry[Index2].Bits.AddressHi);
> > + for (Index1 = 0; Index1 <
> > SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY); Index1++) {
> > + if (Lvl1PtEntry[Index1].Uint64 != 0) {
> > + DEBUG ((DEBUG_VERBOSE," Lvl1Pt Entry(0x%03x) -
> 0x%016lx\n",
> > Index1, Lvl1PtEntry[Index1].Uint64));
> > + }
> > }
> > }
> > }
> > @@ -510,6 +606,7 @@ PageAttributeToLength (
> > @param[in] VtdIndex The index used to identify a VTd engine.
> > @param[in] SecondLevelPagingEntry The second level paging entry in
> > VTd table for the device.
> > @param[in] Address The address to be checked.
> > + @param[in] Is5LevelPaging If it is the 5 level paging.
> > @param[out] PageAttributes The page attribute of the page entry.
> >
> > @return The page entry.
> > @@ -519,6 +616,7 @@ GetSecondLevelPageTableEntry (
> > IN UINTN VtdIndex,
> > IN VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry,
> > IN PHYSICAL_ADDRESS Address,
> > + IN BOOLEAN Is5LevelPaging,
> > OUT PAGE_ATTRIBUTE *PageAttribute
> > )
> > {
> > @@ -526,17 +624,38 @@ GetSecondLevelPageTableEntry (
> > UINTN Index2;
> > UINTN Index3;
> > UINTN Index4;
> > + UINTN Index5;
> > UINT64 *L1PageTable;
> > UINT64 *L2PageTable;
> > UINT64 *L3PageTable;
> > UINT64 *L4PageTable;
> > + UINT64 *L5PageTable;
> >
> > + Index5 = ((UINTN)RShiftU64 (Address, 48)) & PAGING_VTD_INDEX_MASK;
> > Index4 = ((UINTN)RShiftU64 (Address, 39)) & PAGING_VTD_INDEX_MASK;
> > Index3 = ((UINTN)Address >> 30) & PAGING_VTD_INDEX_MASK;
> > Index2 = ((UINTN)Address >> 21) & PAGING_VTD_INDEX_MASK;
> > Index1 = ((UINTN)Address >> 12) & PAGING_VTD_INDEX_MASK;
> >
> > - L4PageTable = (UINT64 *)SecondLevelPagingEntry;
> > + if (Is5LevelPaging) {
> > + L5PageTable = (UINT64 *)SecondLevelPagingEntry;
> > + if (L5PageTable[Index5] == 0) {
> > + L5PageTable[Index5] = (UINT64)(UINTN)AllocateZeroPages (1);
> > + if (L5PageTable[Index5] == 0) {
> > + DEBUG ((DEBUG_ERROR,"!!!!!! ALLOCATE LVL5 PAGE FAIL
> > (0x%x)!!!!!!\n", Index4));
> > + ASSERT(FALSE);
> > + *PageAttribute = PageNone;
> > + return NULL;
> > + }
> > + FlushPageTableMemory (VtdIndex, (UINTN)L5PageTable[Index5],
> > SIZE_4KB);
> > + SetSecondLevelPagingEntryAttribute
> > ((VTD_SECOND_LEVEL_PAGING_ENTRY *)&L5PageTable[Index5],
> > EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);
> > + FlushPageTableMemory (VtdIndex, (UINTN)&L5PageTable[Index5],
> > sizeof(L5PageTable[Index5]));
> > + }
> > + L4PageTable = (UINT64 *)(UINTN)(L5PageTable[Index5] &
> > PAGING_4K_ADDRESS_MASK_64);
> > + } else {
> > + L4PageTable = (UINT64 *)SecondLevelPagingEntry; }
> > +
> > if (L4PageTable[Index4] == 0) {
> > L4PageTable[Index4] = (UINT64)(UINTN)AllocateZeroPages (1);
> > if (L4PageTable[Index4] == 0) {
> > @@ -785,7 +904,7 @@ SetSecondLevelPagingAttribute (
> > }
> >
> > while (Length != 0) {
> > - PageEntry = GetSecondLevelPageTableEntry (VtdIndex,
> > SecondLevelPagingEntry, BaseAddress, &PageAttribute);
> > + PageEntry = GetSecondLevelPageTableEntry (VtdIndex,
> > SecondLevelPagingEntry, BaseAddress,
> > mVtdUnitInformation[VtdIndex].Is5LevelPaging, &PageAttribute);
> > if (PageEntry == NULL) {
> > DEBUG ((DEBUG_ERROR, "PageEntry - NULL\n"));
> > return RETURN_UNSUPPORTED;
> > @@ -913,7 +1032,7 @@ SetAccessAttribute (
> >
> > if (ExtContextEntry != NULL) {
> > if (ExtContextEntry->Bits.Present == 0) {
> > - SecondLevelPagingEntry = CreateSecondLevelPagingEntry (VtdIndex, 0);
> > + SecondLevelPagingEntry = CreateSecondLevelPagingEntry
> > + (VtdIndex, 0,
> > mVtdUnitInformation[VtdIndex].Is5LevelPaging);
> > DEBUG ((DEBUG_VERBOSE,"SecondLevelPagingEntry - 0x%x (S%04x
> > B%02x D%02x F%02x) New\n", SecondLevelPagingEntry, Segment,
> > SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.Function));
> > Pt = (UINT64)RShiftU64 ((UINT64)(UINTN)SecondLevelPagingEntry,
> > 12);
> >
> > @@ -922,7 +1041,7 @@ SetAccessAttribute (
> > ExtContextEntry->Bits.DomainIdentifier = DomainIdentifier;
> > ExtContextEntry->Bits.Present = 1;
> > FlushPageTableMemory (VtdIndex, (UINTN)ExtContextEntry,
> > sizeof(*ExtContextEntry));
> > - DumpDmarExtContextEntryTable
> > (mVtdUnitInformation[VtdIndex].ExtRootEntryTable);
> > + DumpDmarExtContextEntryTable
> > (mVtdUnitInformation[VtdIndex].ExtRootEntryTable,
> > mVtdUnitInformation[VtdIndex].Is5LevelPaging);
> > mVtdUnitInformation[VtdIndex].HasDirtyContext = TRUE;
> > } else {
> > SecondLevelPagingEntry = (VOID
> > *)(UINTN)VTD_64BITS_ADDRESS(ExtContextEntry-
> > >Bits.SecondLevelPageTranslationPointerLo, ExtContextEntry-
> > >Bits.SecondLevelPageTranslationPointerHi);
> > @@ -930,7 +1049,7 @@ SetAccessAttribute (
> > }
> > } else if (ContextEntry != NULL) {
> > if (ContextEntry->Bits.Present == 0) {
> > - SecondLevelPagingEntry = CreateSecondLevelPagingEntry (VtdIndex, 0);
> > + SecondLevelPagingEntry = CreateSecondLevelPagingEntry
> > + (VtdIndex, 0,
> > mVtdUnitInformation[VtdIndex].Is5LevelPaging);
> > DEBUG ((DEBUG_VERBOSE,"SecondLevelPagingEntry - 0x%x (S%04x
> > B%02x D%02x F%02x) New\n", SecondLevelPagingEntry, Segment,
> > SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.Function));
> > Pt = (UINT64)RShiftU64 ((UINT64)(UINTN)SecondLevelPagingEntry,
> > 12);
> >
> > @@ -939,7 +1058,7 @@ SetAccessAttribute (
> > ContextEntry->Bits.DomainIdentifier = DomainIdentifier;
> > ContextEntry->Bits.Present = 1;
> > FlushPageTableMemory (VtdIndex, (UINTN)ContextEntry,
> > sizeof(*ContextEntry));
> > - DumpDmarContextEntryTable
> > (mVtdUnitInformation[VtdIndex].RootEntryTable);
> > + DumpDmarContextEntryTable
> > (mVtdUnitInformation[VtdIndex].RootEntryTable,
> > mVtdUnitInformation[VtdIndex].Is5LevelPaging);
> > mVtdUnitInformation[VtdIndex].HasDirtyContext = TRUE;
> > } else {
> > SecondLevelPagingEntry = (VOID
> > *)(UINTN)VTD_64BITS_ADDRESS(ContextEntry-
> > >Bits.SecondLevelPageTranslationPointerLo, ContextEntry-
> > >Bits.SecondLevelPageTranslationPointerHi);
> > @@ -1000,7 +1119,7 @@ AlwaysEnablePageAttribute (
> >
> > if (mVtdUnitInformation[VtdIndex].FixedSecondLevelPagingEntry == 0) {
> > DEBUG((DEBUG_INFO, "CreateSecondLevelPagingEntry - %d\n",
> > VtdIndex));
> > - mVtdUnitInformation[VtdIndex].FixedSecondLevelPagingEntry =
> > CreateSecondLevelPagingEntry (VtdIndex, EDKII_IOMMU_ACCESS_READ |
> > EDKII_IOMMU_ACCESS_WRITE);
> > + mVtdUnitInformation[VtdIndex].FixedSecondLevelPagingEntry =
> > CreateSecondLevelPagingEntry (VtdIndex, EDKII_IOMMU_ACCESS_READ |
> > EDKII_IOMMU_ACCESS_WRITE,
> > mVtdUnitInformation[VtdIndex].Is5LevelPaging);
> > }
> >
> > SecondLevelPagingEntry =
> > mVtdUnitInformation[VtdIndex].FixedSecondLevelPagingEntry;
> > diff --git
> > a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTableEx.
> > c
> > b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTableEx.
> > c
> > index 0ed9e3ca..3918eeee 100644
> > ---
> > a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTableEx.
> > c
> > +++
> > b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTableEx.
> > c
> > @@ -78,11 +78,32 @@ CreateExtContextEntry (
> >
> > DEBUG ((DEBUG_INFO,"DOMAIN: S%04x, B%02x D%02x F%02x\n",
> > mVtdUnitInformation[VtdIndex].Segment, SourceId.Bits.Bus,
> > SourceId.Bits.Device, SourceId.Bits.Function));
> >
> > - if ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW & BIT2) == 0) {
> > - DEBUG((DEBUG_ERROR, "!!!! 4-level page-table is not supported on
> > VTD %d !!!!\n", VtdIndex));
> > + mVtdUnitInformation[VtdIndex].Is5LevelPaging = FALSE;
> > + if ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW & BIT3) != 0) {
> > + if ((PcdGet8(PcdVTdPolicyPropertyMask) & BIT3) != 0) {
> > + DEBUG((DEBUG_ERROR, "Force to use 4-level page-table on VTD
> > + %d\n",
> > VtdIndex));
> > + ExtContextEntry->Bits.AddressWidth = 0x2;
> > + } if ((PcdGet8(PcdVTdPolicyPropertyMask) & BIT4) != 0) {
> > + DEBUG((DEBUG_ERROR, "Force to use 5-level page-table on VTD
> > + %d\n",
> > VtdIndex));
> > + ExtContextEntry->Bits.AddressWidth = 0x3;
> > + mVtdUnitInformation[VtdIndex].Is5LevelPaging = TRUE;
> > + } else {
> > + if (mAcpiDmarTable->HostAddressWidth > 48) {
> > + DEBUG((DEBUG_ERROR, "Using 5-level page-table on VTD %d\n",
> > VtdIndex));
> > + ExtContextEntry->Bits.AddressWidth = 0x3;
> > + mVtdUnitInformation[VtdIndex].Is5LevelPaging = TRUE;
> > + } else {
> > + DEBUG((DEBUG_ERROR, "Using 4-level page-table on VTD %d\n",
> > VtdIndex));
> > + ExtContextEntry->Bits.AddressWidth = 0x2;
> > + }
> > + }
> > + } else if ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW &
> > + BIT2) !=
> > 0) {
> > + DEBUG((DEBUG_ERROR, "Using 4-level page-table on VTD %d\n",
> > VtdIndex));
> > + ExtContextEntry->Bits.AddressWidth = 0x2;
> > + } else {
> > + DEBUG((DEBUG_ERROR, "!!!! Page-table type is not supported on
> > VTD %d !!!!\n", VtdIndex));
> > return EFI_UNSUPPORTED;
> > }
> > - ExtContextEntry->Bits.AddressWidth = 0x2;
> > }
> >
> > FlushPageTableMemory (VtdIndex,
> > (UINTN)mVtdUnitInformation[VtdIndex].ExtRootEntryTable,
> > EFI_PAGES_TO_SIZE(EntryTablePages));
> > @@ -93,11 +114,13 @@ CreateExtContextEntry (
> > /**
> > Dump DMAR extended context entry table.
> >
> > - @param[in] ExtRootEntry DMAR extended root entry.
> > + @param[in] ExtRootEntry DMAR extended root entry.
> > + @param[in] Is5LevelPaging If it is the 5 level paging.
> > **/
> > VOID
> > DumpDmarExtContextEntryTable (
> > - IN VTD_EXT_ROOT_ENTRY *ExtRootEntry
> > + IN VTD_EXT_ROOT_ENTRY *ExtRootEntry, IN BOOLEAN Is5LevelPaging
> > )
> > {
> > UINTN Index;
> > @@ -127,7 +150,7 @@ DumpDmarExtContextEntryTable (
> > if (ExtContextEntry[Index2].Bits.Present == 0) {
> > continue;
> > }
> > - DumpSecondLevelPagingEntry ((VOID
> > *)(UINTN)VTD_64BITS_ADDRESS(ExtContextEntry[Index2].Bits.SecondLevelPa
> > geTranslationPointerLo,
> > ExtContextEntry[Index2].Bits.SecondLevelPageTranslationPointerHi));
> > + DumpSecondLevelPagingEntry ((VOID
> > *)(UINTN)VTD_64BITS_ADDRESS(ExtContextEntry[Index2].Bits.SecondLevelPa
> > geTranslationPointerLo,
> > ExtContextEntry[Index2].Bits.SecondLevelPageTranslationPointerHi),
> > Is5LevelPaging);
> > }
> >
> > if (ExtRootEntry[Index].Bits.UpperPresent == 0) { diff --git
> > a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/VtdReg.c
> > b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/VtdReg.c
> > index 699639ba..686d235f 100644
> > --- a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/VtdReg.c
> > +++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/VtdReg.c
> > @@ -174,8 +174,14 @@ PrepareVtdConfig (
> > if ((mVtdUnitInformation[Index].CapReg.Bits.SLLPS & BIT0) == 0) {
> > DEBUG((DEBUG_WARN, "!!!! 2MB super page is not supported on VTD
> > %d !!!!\n", Index));
> > }
> > - if ((mVtdUnitInformation[Index].CapReg.Bits.SAGAW & BIT2) == 0) {
> > - DEBUG((DEBUG_ERROR, "!!!! 4-level page-table is not supported on
> > VTD %d !!!!\n", Index));
> > + if ((mVtdUnitInformation[Index].CapReg.Bits.SAGAW & BIT3) != 0) {
> > + DEBUG((DEBUG_INFO, "Support 5-level page-table on VTD %d\n",
> > Index));
> > + }
> > + if ((mVtdUnitInformation[Index].CapReg.Bits.SAGAW & BIT2) != 0) {
> > + DEBUG((DEBUG_INFO, "Support 4-level page-table on VTD %d\n",
> > Index));
> > + }
> > + if ((mVtdUnitInformation[Index].CapReg.Bits.SAGAW & (BIT3 |
> > + BIT2)) == 0)
> > {
> > + DEBUG((DEBUG_ERROR, "!!!! Page-table type 0x%X is not supported
> > + on
> > VTD %d !!!!\n", Index, mVtdUnitInformation[Index].CapReg.Bits.SAGAW));
> > return ;
> > }
> >
> > diff --git a/Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dec
> > b/Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dec
> > index 284820af..8f1edfe2 100644
> > --- a/Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dec
> > +++ b/Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dec
> > @@ -95,6 +95,9 @@
> > # BIT0: Enable IOMMU during boot (If DMAR table is installed in
> > DXE. If VTD_INFO_PPI is installed in PEI.)
> > # BIT1: Enable IOMMU when transfer control to OS (ExitBootService
> > in normal boot. EndOfPEI in S3)
> > # BIT2: Force no IOMMU access attribute request recording before
> > DMAR table is installed.
> > + # BIT3: Force to use 4 level paging.
> > + # BIT4: If iommu support 5 level paging, force to use 5 level paging.
> > + # (If both BIT3 and BIT4 are set, force to use 4 level paging.)
> > # @Prompt The policy for VTd driver behavior.
> >
> > gIntelSiliconPkgTokenSpaceGuid.PcdVTdPolicyPropertyMask|1|UINT8|0x000
> > 00002
> >
> > --
> > 2.16.2.windows.1
[-- Attachment #2: 0001-IntelSiliconPkg-VTd-Add-iommu-5-level-paging-support.patch --]
[-- Type: application/octet-stream, Size: 36592 bytes --]
From 2bc917b9f5eb0f321d824286927535b7a317bc2f Mon Sep 17 00:00:00 2001
From: Sheng Wei <w.sheng@intel.com>
Date: Thu, 22 Oct 2020 09:52:29 +0800
Subject: [PATCH v3] IntelSiliconPkg/VTd: Add iommu 5 level paging support
Support iommu 5 level paging for translation table.
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3067
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: Jiewen Yao <jiewen.yao@intel.com>
Cc: Jenny Huang <jenny.huang@intel.com>
---
.../Feature/VTd/IntelVTdDxe/DmaProtection.c | 4 +-
.../Feature/VTd/IntelVTdDxe/DmaProtection.h | 19 +-
.../Feature/VTd/IntelVTdDxe/TranslationTable.c | 287 +++++++++++++++------
.../Feature/VTd/IntelVTdDxe/TranslationTableEx.c | 35 ++-
.../Feature/VTd/IntelVTdDxe/VtdReg.c | 10 +-
Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dec | 3 +
6 files changed, 258 insertions(+), 100 deletions(-)
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.c
index 9b6135ef..628565ee 100644
--- a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.c
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.c
@@ -523,10 +523,10 @@ SetupVtd (
for (Index = 0; Index < mVtdUnitNumber; Index++) {
DEBUG ((DEBUG_INFO,"VTD Unit %d (Segment: %04x)\n", Index, mVtdUnitInformation[Index].Segment));
if (mVtdUnitInformation[Index].ExtRootEntryTable != NULL) {
- DumpDmarExtContextEntryTable (mVtdUnitInformation[Index].ExtRootEntryTable);
+ DumpDmarExtContextEntryTable (mVtdUnitInformation[Index].ExtRootEntryTable, mVtdUnitInformation[Index].Is5LevelPaging);
}
if (mVtdUnitInformation[Index].RootEntryTable != NULL) {
- DumpDmarContextEntryTable (mVtdUnitInformation[Index].RootEntryTable);
+ DumpDmarContextEntryTable (mVtdUnitInformation[Index].RootEntryTable, mVtdUnitInformation[Index].Is5LevelPaging);
}
}
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.h b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.h
index a3331db8..f641cea0 100644
--- a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.h
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.h
@@ -77,6 +77,7 @@ typedef struct {
BOOLEAN HasDirtyContext;
BOOLEAN HasDirtyPages;
PCI_DEVICE_INFORMATION PciDeviceInfo;
+ BOOLEAN Is5LevelPaging;
} VTD_UNIT_INFORMATION;
//
@@ -375,31 +376,37 @@ ParseDmarAcpiTableRmrr (
/**
Dump DMAR context entry table.
- @param[in] RootEntry DMAR root entry.
+ @param[in] RootEntry DMAR root entry.
+ @param[in] Is5LevelPaging If it is the 5 level paging.
**/
VOID
DumpDmarContextEntryTable (
- IN VTD_ROOT_ENTRY *RootEntry
+ IN VTD_ROOT_ENTRY *RootEntry,
+ IN BOOLEAN Is5LevelPaging
);
/**
Dump DMAR extended context entry table.
- @param[in] ExtRootEntry DMAR extended root entry.
+ @param[in] ExtRootEntry DMAR extended root entry.
+ @param[in] Is5LevelPaging If it is the 5 level paging.
**/
VOID
DumpDmarExtContextEntryTable (
- IN VTD_EXT_ROOT_ENTRY *ExtRootEntry
+ IN VTD_EXT_ROOT_ENTRY *ExtRootEntry,
+ IN BOOLEAN Is5LevelPaging
);
/**
Dump DMAR second level paging entry.
- @param[in] SecondLevelPagingEntry The second level paging entry.
+ @param[in] SecondLevelPagingEntry The second level paging entry.
+ @param[in] Is5LevelPaging If it is the 5 level paging.
**/
VOID
DumpSecondLevelPagingEntry (
- IN VOID *SecondLevelPagingEntry
+ IN VOID *SecondLevelPagingEntry,
+ IN BOOLEAN Is5LevelPaging
);
/**
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTable.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTable.c
index 201d663d..cb59860a 100644
--- a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTable.c
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTable.c
@@ -128,11 +128,32 @@ CreateContextEntry (
DEBUG ((DEBUG_INFO,"Source: S%04x B%02x D%02x F%02x\n", mVtdUnitInformation[VtdIndex].Segment, SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.Function));
- if ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW & BIT2) == 0) {
- DEBUG((DEBUG_ERROR, "!!!! 4-level page-table is not supported on VTD %d !!!!\n", VtdIndex));
+ mVtdUnitInformation[VtdIndex].Is5LevelPaging = FALSE;
+ if ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW & BIT3) != 0) {
+ if ((PcdGet8(PcdVTdPolicyPropertyMask) & BIT3) != 0) {
+ DEBUG((DEBUG_ERROR, "Force to use 4-level page-table on VTD %d\n", VtdIndex));
+ ContextEntry->Bits.AddressWidth = 0x2;
+ } if ((PcdGet8(PcdVTdPolicyPropertyMask) & BIT4) != 0) {
+ DEBUG((DEBUG_ERROR, "Force to use 5-level page-table on VTD %d\n", VtdIndex));
+ ContextEntry->Bits.AddressWidth = 0x3;
+ mVtdUnitInformation[VtdIndex].Is5LevelPaging = TRUE;
+ } else {
+ if (mAcpiDmarTable->HostAddressWidth > 48) {
+ DEBUG((DEBUG_ERROR, "Using 5-level page-table on VTD %d\n", VtdIndex));
+ ContextEntry->Bits.AddressWidth = 0x3;
+ mVtdUnitInformation[VtdIndex].Is5LevelPaging = TRUE;
+ } else {
+ DEBUG((DEBUG_ERROR, "Using 4-level page-table on VTD %d\n", VtdIndex));
+ ContextEntry->Bits.AddressWidth = 0x2;
+ }
+ }
+ } else if ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW & BIT2) != 0) {
+ DEBUG((DEBUG_ERROR, "Using 4-level page-table on VTD %d\n", VtdIndex));
+ ContextEntry->Bits.AddressWidth = 0x2;
+ } else {
+ DEBUG((DEBUG_ERROR, "!!!! Page-table type is not supported on VTD %d !!!!\n", VtdIndex));
return EFI_UNSUPPORTED;
}
- ContextEntry->Bits.AddressWidth = 0x2;
}
FlushPageTableMemory (VtdIndex, (UINTN)mVtdUnitInformation[VtdIndex].RootEntryTable, EFI_PAGES_TO_SIZE(EntryTablePages));
@@ -148,6 +169,7 @@ CreateContextEntry (
@param[in] MemoryBase The base of the memory.
@param[in] MemoryLimit The limit of the memory.
@param[in] IoMmuAccess The IOMMU access.
+ @param[in] Is5LevelPaging If it is the 5 level paging.
@return The second level paging entry.
**/
@@ -157,16 +179,23 @@ CreateSecondLevelPagingEntryTable (
IN VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry,
IN UINT64 MemoryBase,
IN UINT64 MemoryLimit,
- IN UINT64 IoMmuAccess
+ IN UINT64 IoMmuAccess,
+ IN BOOLEAN Is5LevelPaging
)
{
+ UINTN Index5;
UINTN Index4;
UINTN Index3;
UINTN Index2;
+ UINTN Lvl5Start;
+ UINTN Lvl5End;
+ UINTN Lvl4PagesStart;
+ UINTN Lvl4PagesEnd;
UINTN Lvl4Start;
UINTN Lvl4End;
UINTN Lvl3Start;
UINTN Lvl3End;
+ VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl5PtEntry;
VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl4PtEntry;
VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl3PtEntry;
VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl2PtEntry;
@@ -184,7 +213,7 @@ CreateSecondLevelPagingEntryTable (
if (SecondLevelPagingEntry == NULL) {
SecondLevelPagingEntry = AllocateZeroPages (1);
if (SecondLevelPagingEntry == NULL) {
- DEBUG ((DEBUG_ERROR,"Could not Alloc LVL4 PT. \n"));
+ DEBUG ((DEBUG_ERROR,"Could not Alloc LVL4 or LVL5 PT. \n"));
return NULL;
}
FlushPageTableMemory (VtdIndex, (UINTN)SecondLevelPagingEntry, EFI_PAGES_TO_SIZE(1));
@@ -197,66 +226,109 @@ CreateSecondLevelPagingEntryTable (
return SecondLevelPagingEntry;
}
- Lvl4Start = RShiftU64 (BaseAddress, 39) & 0x1FF;
- Lvl4End = RShiftU64 (EndAddress - 1, 39) & 0x1FF;
+ if (Is5LevelPaging) {
+ Lvl5Start = RShiftU64 (BaseAddress, 48) & 0x1FF;
+ Lvl5End = RShiftU64 (EndAddress - 1, 48) & 0x1FF;
+ DEBUG ((DEBUG_INFO," Lvl5Start - 0x%x, Lvl5End - 0x%x\n", Lvl5Start, Lvl5End));
- DEBUG ((DEBUG_INFO," Lvl4Start - 0x%x, Lvl4End - 0x%x\n", Lvl4Start, Lvl4End));
+ Lvl4Start = RShiftU64 (BaseAddress, 39) & 0x1FF;
+ Lvl4End = RShiftU64 (EndAddress - 1, 39) & 0x1FF;
- Lvl4PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY *)SecondLevelPagingEntry;
- for (Index4 = Lvl4Start; Index4 <= Lvl4End; Index4++) {
- if (Lvl4PtEntry[Index4].Uint64 == 0) {
- Lvl4PtEntry[Index4].Uint64 = (UINT64)(UINTN)AllocateZeroPages (1);
- if (Lvl4PtEntry[Index4].Uint64 == 0) {
- DEBUG ((DEBUG_ERROR,"!!!!!! ALLOCATE LVL4 PAGE FAIL (0x%x)!!!!!!\n", Index4));
- ASSERT(FALSE);
- return NULL;
- }
- FlushPageTableMemory (VtdIndex, (UINTN)Lvl4PtEntry[Index4].Uint64, SIZE_4KB);
- SetSecondLevelPagingEntryAttribute (&Lvl4PtEntry[Index4], EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);
- }
+ Lvl4PagesStart = (Lvl5Start<<9) | Lvl4Start;
+ Lvl4PagesEnd = (Lvl5End<<9) | Lvl4End;
+ DEBUG ((DEBUG_INFO," Lvl4PagesStart - 0x%x, Lvl4PagesEnd - 0x%x\n", Lvl4PagesStart, Lvl4PagesEnd));
- Lvl3Start = RShiftU64 (BaseAddress, 30) & 0x1FF;
- if (ALIGN_VALUE_LOW(BaseAddress + SIZE_1GB, SIZE_1GB) <= EndAddress) {
- Lvl3End = SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY) - 1;
- } else {
- Lvl3End = RShiftU64 (EndAddress - 1, 30) & 0x1FF;
+ Lvl5PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY *)SecondLevelPagingEntry;
+ } else {
+ Lvl5Start = RShiftU64 (BaseAddress, 48) & 0x1FF;
+ Lvl5End = Lvl5Start;
+
+ Lvl4Start = RShiftU64 (BaseAddress, 39) & 0x1FF;
+ Lvl4End = RShiftU64 (EndAddress - 1, 39) & 0x1FF;
+ DEBUG ((DEBUG_INFO," Lvl4Start - 0x%x, Lvl4End - 0x%x\n", Lvl4Start, Lvl4End));
+
+ Lvl4PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY *)SecondLevelPagingEntry;
+ }
+
+ for (Index5 = Lvl5Start; Index5 <= Lvl5End; Index5++) {
+ if (Is5LevelPaging) {
+ if (Lvl5PtEntry[Index5].Uint64 == 0) {
+ Lvl5PtEntry[Index5].Uint64 = (UINT64)(UINTN)AllocateZeroPages (1);
+ if (Lvl5PtEntry[Index5].Uint64 == 0) {
+ DEBUG ((DEBUG_ERROR,"!!!!!! ALLOCATE LVL4 PAGE FAIL (0x%x)!!!!!!\n", Index5));
+ ASSERT(FALSE);
+ return NULL;
+ }
+ FlushPageTableMemory (VtdIndex, (UINTN)Lvl5PtEntry[Index5].Uint64, SIZE_4KB);
+ SetSecondLevelPagingEntryAttribute (&Lvl5PtEntry[Index5], EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);
+ }
+ Lvl4Start = Lvl4PagesStart & 0x1FF;
+ if (((Index5+1)<<9) > Lvl4PagesEnd) {
+ Lvl4End = SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY) - 1;;
+ Lvl4PagesStart = (Index5+1)<<9;
+ } else {
+ Lvl4End = Lvl4PagesEnd & 0x1FF;
+ }
+ DEBUG ((DEBUG_INFO," Lvl5(0x%x): Lvl4Start - 0x%x, Lvl4End - 0x%x\n", Index5, Lvl4Start, Lvl4End));
+ Lvl4PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY *)(UINTN)VTD_64BITS_ADDRESS(Lvl5PtEntry[Index5].Bits.AddressLo, Lvl5PtEntry[Index5].Bits.AddressHi);
}
- DEBUG ((DEBUG_INFO," Lvl4(0x%x): Lvl3Start - 0x%x, Lvl3End - 0x%x\n", Index4, Lvl3Start, Lvl3End));
- Lvl3PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY *)(UINTN)VTD_64BITS_ADDRESS(Lvl4PtEntry[Index4].Bits.AddressLo, Lvl4PtEntry[Index4].Bits.AddressHi);
- for (Index3 = Lvl3Start; Index3 <= Lvl3End; Index3++) {
- if (Lvl3PtEntry[Index3].Uint64 == 0) {
- Lvl3PtEntry[Index3].Uint64 = (UINT64)(UINTN)AllocateZeroPages (1);
- if (Lvl3PtEntry[Index3].Uint64 == 0) {
- DEBUG ((DEBUG_ERROR,"!!!!!! ALLOCATE LVL3 PAGE FAIL (0x%x, 0x%x)!!!!!!\n", Index4, Index3));
+ for (Index4 = Lvl4Start; Index4 <= Lvl4End; Index4++) {
+ if (Lvl4PtEntry[Index4].Uint64 == 0) {
+ Lvl4PtEntry[Index4].Uint64 = (UINT64)(UINTN)AllocateZeroPages (1);
+ if (Lvl4PtEntry[Index4].Uint64 == 0) {
+ DEBUG ((DEBUG_ERROR,"!!!!!! ALLOCATE LVL4 PAGE FAIL (0x%x)!!!!!!\n", Index4));
ASSERT(FALSE);
return NULL;
}
- FlushPageTableMemory (VtdIndex, (UINTN)Lvl3PtEntry[Index3].Uint64, SIZE_4KB);
- SetSecondLevelPagingEntryAttribute (&Lvl3PtEntry[Index3], EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);
+ FlushPageTableMemory (VtdIndex, (UINTN)Lvl4PtEntry[Index4].Uint64, SIZE_4KB);
+ SetSecondLevelPagingEntryAttribute (&Lvl4PtEntry[Index4], EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);
}
- Lvl2PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY *)(UINTN)VTD_64BITS_ADDRESS(Lvl3PtEntry[Index3].Bits.AddressLo, Lvl3PtEntry[Index3].Bits.AddressHi);
- for (Index2 = 0; Index2 < SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY); Index2++) {
- Lvl2PtEntry[Index2].Uint64 = BaseAddress;
- SetSecondLevelPagingEntryAttribute (&Lvl2PtEntry[Index2], IoMmuAccess);
- Lvl2PtEntry[Index2].Bits.PageSize = 1;
- BaseAddress += SIZE_2MB;
+ Lvl3Start = RShiftU64 (BaseAddress, 30) & 0x1FF;
+ if (ALIGN_VALUE_LOW(BaseAddress + SIZE_1GB, SIZE_1GB) <= EndAddress) {
+ Lvl3End = SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY) - 1;
+ } else {
+ Lvl3End = RShiftU64 (EndAddress - 1, 30) & 0x1FF;
+ }
+ DEBUG ((DEBUG_INFO," Lvl4(0x%x): Lvl3Start - 0x%x, Lvl3End - 0x%x\n", Index4, Lvl3Start, Lvl3End));
+
+ Lvl3PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY *)(UINTN)VTD_64BITS_ADDRESS(Lvl4PtEntry[Index4].Bits.AddressLo, Lvl4PtEntry[Index4].Bits.AddressHi);
+ for (Index3 = Lvl3Start; Index3 <= Lvl3End; Index3++) {
+ if (Lvl3PtEntry[Index3].Uint64 == 0) {
+ Lvl3PtEntry[Index3].Uint64 = (UINT64)(UINTN)AllocateZeroPages (1);
+ if (Lvl3PtEntry[Index3].Uint64 == 0) {
+ DEBUG ((DEBUG_ERROR,"!!!!!! ALLOCATE LVL3 PAGE FAIL (0x%x, 0x%x)!!!!!!\n", Index4, Index3));
+ ASSERT(FALSE);
+ return NULL;
+ }
+ FlushPageTableMemory (VtdIndex, (UINTN)Lvl3PtEntry[Index3].Uint64, SIZE_4KB);
+ SetSecondLevelPagingEntryAttribute (&Lvl3PtEntry[Index3], EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);
+ }
+
+ Lvl2PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY *)(UINTN)VTD_64BITS_ADDRESS(Lvl3PtEntry[Index3].Bits.AddressLo, Lvl3PtEntry[Index3].Bits.AddressHi);
+ for (Index2 = 0; Index2 < SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY); Index2++) {
+ Lvl2PtEntry[Index2].Uint64 = BaseAddress;
+ SetSecondLevelPagingEntryAttribute (&Lvl2PtEntry[Index2], IoMmuAccess);
+ Lvl2PtEntry[Index2].Bits.PageSize = 1;
+ BaseAddress += SIZE_2MB;
+ if (BaseAddress >= MemoryLimit) {
+ break;
+ }
+ }
+ FlushPageTableMemory (VtdIndex, (UINTN)Lvl2PtEntry, SIZE_4KB);
if (BaseAddress >= MemoryLimit) {
break;
}
}
- FlushPageTableMemory (VtdIndex, (UINTN)Lvl2PtEntry, SIZE_4KB);
+ FlushPageTableMemory (VtdIndex, (UINTN)&Lvl3PtEntry[Lvl3Start], (UINTN)&Lvl3PtEntry[Lvl3End + 1] - (UINTN)&Lvl3PtEntry[Lvl3Start]);
if (BaseAddress >= MemoryLimit) {
break;
}
}
- FlushPageTableMemory (VtdIndex, (UINTN)&Lvl3PtEntry[Lvl3Start], (UINTN)&Lvl3PtEntry[Lvl3End + 1] - (UINTN)&Lvl3PtEntry[Lvl3Start]);
- if (BaseAddress >= MemoryLimit) {
- break;
- }
+ FlushPageTableMemory (VtdIndex, (UINTN)&Lvl4PtEntry[Lvl4Start], (UINTN)&Lvl4PtEntry[Lvl4End + 1] - (UINTN)&Lvl4PtEntry[Lvl4Start]);
}
- FlushPageTableMemory (VtdIndex, (UINTN)&Lvl4PtEntry[Lvl4Start], (UINTN)&Lvl4PtEntry[Lvl4End + 1] - (UINTN)&Lvl4PtEntry[Lvl4Start]);
+ FlushPageTableMemory (VtdIndex, (UINTN)&Lvl5PtEntry[Lvl5Start], (UINTN)&Lvl5PtEntry[Lvl5End + 1] - (UINTN)&Lvl5PtEntry[Lvl5Start]);
return SecondLevelPagingEntry;
}
@@ -266,26 +338,28 @@ CreateSecondLevelPagingEntryTable (
@param[in] VtdIndex The index of the VTd engine.
@param[in] IoMmuAccess The IOMMU access.
+ @param[in] Is5LevelPaging If it is the 5 level paging.
@return The second level paging entry.
**/
VTD_SECOND_LEVEL_PAGING_ENTRY *
CreateSecondLevelPagingEntry (
IN UINTN VtdIndex,
- IN UINT64 IoMmuAccess
+ IN UINT64 IoMmuAccess,
+ IN BOOLEAN Is5LevelPaging
)
{
VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry;
SecondLevelPagingEntry = NULL;
- SecondLevelPagingEntry = CreateSecondLevelPagingEntryTable (VtdIndex, SecondLevelPagingEntry, 0, mBelow4GMemoryLimit, IoMmuAccess);
+ SecondLevelPagingEntry = CreateSecondLevelPagingEntryTable (VtdIndex, SecondLevelPagingEntry, 0, mBelow4GMemoryLimit, IoMmuAccess, Is5LevelPaging);
if (SecondLevelPagingEntry == NULL) {
return NULL;
}
if (mAbove4GMemoryLimit != 0) {
ASSERT (mAbove4GMemoryLimit > BASE_4GB);
- SecondLevelPagingEntry = CreateSecondLevelPagingEntryTable (VtdIndex, SecondLevelPagingEntry, SIZE_4GB, mAbove4GMemoryLimit, IoMmuAccess);
+ SecondLevelPagingEntry = CreateSecondLevelPagingEntryTable (VtdIndex, SecondLevelPagingEntry, SIZE_4GB, mAbove4GMemoryLimit, IoMmuAccess, Is5LevelPaging);
if (SecondLevelPagingEntry == NULL) {
return NULL;
}
@@ -326,11 +400,13 @@ SetupTranslationTable (
/**
Dump DMAR context entry table.
- @param[in] RootEntry DMAR root entry.
+ @param[in] RootEntry DMAR root entry.
+ @param[in] Is5LevelPaging If it is the 5 level paging.
**/
VOID
DumpDmarContextEntryTable (
- IN VTD_ROOT_ENTRY *RootEntry
+ IN VTD_ROOT_ENTRY *RootEntry,
+ IN BOOLEAN Is5LevelPaging
)
{
UINTN Index;
@@ -359,7 +435,7 @@ DumpDmarContextEntryTable (
if (ContextEntry[Index2].Bits.Present == 0) {
continue;
}
- DumpSecondLevelPagingEntry ((VOID *)(UINTN)VTD_64BITS_ADDRESS(ContextEntry[Index2].Bits.SecondLevelPageTranslationPointerLo, ContextEntry[Index2].Bits.SecondLevelPageTranslationPointerHi));
+ DumpSecondLevelPagingEntry ((VOID *)(UINTN)VTD_64BITS_ADDRESS(ContextEntry[Index2].Bits.SecondLevelPageTranslationPointerLo, ContextEntry[Index2].Bits.SecondLevelPageTranslationPointerHi), Is5LevelPaging);
}
}
DEBUG ((DEBUG_INFO,"=========================\n"));
@@ -368,17 +444,22 @@ DumpDmarContextEntryTable (
/**
Dump DMAR second level paging entry.
- @param[in] SecondLevelPagingEntry The second level paging entry.
+ @param[in] SecondLevelPagingEntry The second level paging entry.
+ @param[in] Is5LevelPaging If it is the 5 level paging.
**/
VOID
DumpSecondLevelPagingEntry (
- IN VOID *SecondLevelPagingEntry
+ IN VOID *SecondLevelPagingEntry,
+ IN BOOLEAN Is5LevelPaging
)
{
+ UINTN Index5;
UINTN Index4;
UINTN Index3;
UINTN Index2;
UINTN Index1;
+ UINTN Lvl5IndexEnd;
+ VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl5PtEntry;
VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl4PtEntry;
VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl3PtEntry;
VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl2PtEntry;
@@ -386,38 +467,53 @@ DumpSecondLevelPagingEntry (
DEBUG ((DEBUG_VERBOSE,"================\n"));
DEBUG ((DEBUG_VERBOSE,"DMAR Second Level Page Table:\n"));
+ DEBUG ((DEBUG_VERBOSE,"SecondLevelPagingEntry Base - 0x%x, Is5LevelPaging - %d\n", SecondLevelPagingEntry, Is5LevelPaging));
- DEBUG ((DEBUG_VERBOSE,"SecondLevelPagingEntry Base - 0x%x\n", SecondLevelPagingEntry));
+ Lvl5IndexEnd = Is5LevelPaging ? SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY) : 1;
Lvl4PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY *)SecondLevelPagingEntry;
- for (Index4 = 0; Index4 < SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY); Index4++) {
- if (Lvl4PtEntry[Index4].Uint64 != 0) {
- DEBUG ((DEBUG_VERBOSE," Lvl4Pt Entry(0x%03x) - 0x%016lx\n", Index4, Lvl4PtEntry[Index4].Uint64));
- }
- if (Lvl4PtEntry[Index4].Uint64 == 0) {
- continue;
- }
- Lvl3PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY *)(UINTN)VTD_64BITS_ADDRESS(Lvl4PtEntry[Index4].Bits.AddressLo, Lvl4PtEntry[Index4].Bits.AddressHi);
- for (Index3 = 0; Index3 < SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY); Index3++) {
- if (Lvl3PtEntry[Index3].Uint64 != 0) {
- DEBUG ((DEBUG_VERBOSE," Lvl3Pt Entry(0x%03x) - 0x%016lx\n", Index3, Lvl3PtEntry[Index3].Uint64));
+ Lvl5PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY *)SecondLevelPagingEntry;
+
+ for (Index5 = 0; Index5 < Lvl5IndexEnd; Index5++) {
+ if (Is5LevelPaging) {
+ if (Lvl5PtEntry[Index5].Uint64 != 0) {
+ DEBUG ((DEBUG_VERBOSE," Lvl5Pt Entry(0x%03x) - 0x%016lx\n", Index5, Lvl5PtEntry[Index5].Uint64));
}
- if (Lvl3PtEntry[Index3].Uint64 == 0) {
+ if (Lvl5PtEntry[Index5].Uint64 == 0) {
continue;
}
+ Lvl4PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY *)(UINTN)VTD_64BITS_ADDRESS(Lvl5PtEntry[Index5].Bits.AddressLo, Lvl5PtEntry[Index5].Bits.AddressHi);
+ }
- Lvl2PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY *)(UINTN)VTD_64BITS_ADDRESS(Lvl3PtEntry[Index3].Bits.AddressLo, Lvl3PtEntry[Index3].Bits.AddressHi);
- for (Index2 = 0; Index2 < SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY); Index2++) {
- if (Lvl2PtEntry[Index2].Uint64 != 0) {
- DEBUG ((DEBUG_VERBOSE," Lvl2Pt Entry(0x%03x) - 0x%016lx\n", Index2, Lvl2PtEntry[Index2].Uint64));
+ for (Index4 = 0; Index4 < SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY); Index4++) {
+ if (Lvl4PtEntry[Index4].Uint64 != 0) {
+ DEBUG ((DEBUG_VERBOSE," Lvl4Pt Entry(0x%03x) - 0x%016lx\n", Index4, Lvl4PtEntry[Index4].Uint64));
+ }
+ if (Lvl4PtEntry[Index4].Uint64 == 0) {
+ continue;
+ }
+ Lvl3PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY *)(UINTN)VTD_64BITS_ADDRESS(Lvl4PtEntry[Index4].Bits.AddressLo, Lvl4PtEntry[Index4].Bits.AddressHi);
+ for (Index3 = 0; Index3 < SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY); Index3++) {
+ if (Lvl3PtEntry[Index3].Uint64 != 0) {
+ DEBUG ((DEBUG_VERBOSE," Lvl3Pt Entry(0x%03x) - 0x%016lx\n", Index3, Lvl3PtEntry[Index3].Uint64));
}
- if (Lvl2PtEntry[Index2].Uint64 == 0) {
+ if (Lvl3PtEntry[Index3].Uint64 == 0) {
continue;
}
- if (Lvl2PtEntry[Index2].Bits.PageSize == 0) {
- Lvl1PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY *)(UINTN)VTD_64BITS_ADDRESS(Lvl2PtEntry[Index2].Bits.AddressLo, Lvl2PtEntry[Index2].Bits.AddressHi);
- for (Index1 = 0; Index1 < SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY); Index1++) {
- if (Lvl1PtEntry[Index1].Uint64 != 0) {
- DEBUG ((DEBUG_VERBOSE," Lvl1Pt Entry(0x%03x) - 0x%016lx\n", Index1, Lvl1PtEntry[Index1].Uint64));
+
+ Lvl2PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY *)(UINTN)VTD_64BITS_ADDRESS(Lvl3PtEntry[Index3].Bits.AddressLo, Lvl3PtEntry[Index3].Bits.AddressHi);
+ for (Index2 = 0; Index2 < SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY); Index2++) {
+ if (Lvl2PtEntry[Index2].Uint64 != 0) {
+ DEBUG ((DEBUG_VERBOSE," Lvl2Pt Entry(0x%03x) - 0x%016lx\n", Index2, Lvl2PtEntry[Index2].Uint64));
+ }
+ if (Lvl2PtEntry[Index2].Uint64 == 0) {
+ continue;
+ }
+ if (Lvl2PtEntry[Index2].Bits.PageSize == 0) {
+ Lvl1PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY *)(UINTN)VTD_64BITS_ADDRESS(Lvl2PtEntry[Index2].Bits.AddressLo, Lvl2PtEntry[Index2].Bits.AddressHi);
+ for (Index1 = 0; Index1 < SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY); Index1++) {
+ if (Lvl1PtEntry[Index1].Uint64 != 0) {
+ DEBUG ((DEBUG_VERBOSE," Lvl1Pt Entry(0x%03x) - 0x%016lx\n", Index1, Lvl1PtEntry[Index1].Uint64));
+ }
}
}
}
@@ -510,6 +606,7 @@ PageAttributeToLength (
@param[in] VtdIndex The index used to identify a VTd engine.
@param[in] SecondLevelPagingEntry The second level paging entry in VTd table for the device.
@param[in] Address The address to be checked.
+ @param[in] Is5LevelPaging If it is the 5 level paging.
@param[out] PageAttributes The page attribute of the page entry.
@return The page entry.
@@ -519,6 +616,7 @@ GetSecondLevelPageTableEntry (
IN UINTN VtdIndex,
IN VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry,
IN PHYSICAL_ADDRESS Address,
+ IN BOOLEAN Is5LevelPaging,
OUT PAGE_ATTRIBUTE *PageAttribute
)
{
@@ -526,17 +624,38 @@ GetSecondLevelPageTableEntry (
UINTN Index2;
UINTN Index3;
UINTN Index4;
+ UINTN Index5;
UINT64 *L1PageTable;
UINT64 *L2PageTable;
UINT64 *L3PageTable;
UINT64 *L4PageTable;
+ UINT64 *L5PageTable;
+ Index5 = ((UINTN)RShiftU64 (Address, 48)) & PAGING_VTD_INDEX_MASK;
Index4 = ((UINTN)RShiftU64 (Address, 39)) & PAGING_VTD_INDEX_MASK;
Index3 = ((UINTN)Address >> 30) & PAGING_VTD_INDEX_MASK;
Index2 = ((UINTN)Address >> 21) & PAGING_VTD_INDEX_MASK;
Index1 = ((UINTN)Address >> 12) & PAGING_VTD_INDEX_MASK;
- L4PageTable = (UINT64 *)SecondLevelPagingEntry;
+ if (Is5LevelPaging) {
+ L5PageTable = (UINT64 *)SecondLevelPagingEntry;
+ if (L5PageTable[Index5] == 0) {
+ L5PageTable[Index5] = (UINT64)(UINTN)AllocateZeroPages (1);
+ if (L5PageTable[Index5] == 0) {
+ DEBUG ((DEBUG_ERROR,"!!!!!! ALLOCATE LVL5 PAGE FAIL (0x%x)!!!!!!\n", Index4));
+ ASSERT(FALSE);
+ *PageAttribute = PageNone;
+ return NULL;
+ }
+ FlushPageTableMemory (VtdIndex, (UINTN)L5PageTable[Index5], SIZE_4KB);
+ SetSecondLevelPagingEntryAttribute ((VTD_SECOND_LEVEL_PAGING_ENTRY *)&L5PageTable[Index5], EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);
+ FlushPageTableMemory (VtdIndex, (UINTN)&L5PageTable[Index5], sizeof(L5PageTable[Index5]));
+ }
+ L4PageTable = (UINT64 *)(UINTN)(L5PageTable[Index5] & PAGING_4K_ADDRESS_MASK_64);
+ } else {
+ L4PageTable = (UINT64 *)SecondLevelPagingEntry;
+ }
+
if (L4PageTable[Index4] == 0) {
L4PageTable[Index4] = (UINT64)(UINTN)AllocateZeroPages (1);
if (L4PageTable[Index4] == 0) {
@@ -785,7 +904,7 @@ SetSecondLevelPagingAttribute (
}
while (Length != 0) {
- PageEntry = GetSecondLevelPageTableEntry (VtdIndex, SecondLevelPagingEntry, BaseAddress, &PageAttribute);
+ PageEntry = GetSecondLevelPageTableEntry (VtdIndex, SecondLevelPagingEntry, BaseAddress, mVtdUnitInformation[VtdIndex].Is5LevelPaging, &PageAttribute);
if (PageEntry == NULL) {
DEBUG ((DEBUG_ERROR, "PageEntry - NULL\n"));
return RETURN_UNSUPPORTED;
@@ -913,7 +1032,7 @@ SetAccessAttribute (
if (ExtContextEntry != NULL) {
if (ExtContextEntry->Bits.Present == 0) {
- SecondLevelPagingEntry = CreateSecondLevelPagingEntry (VtdIndex, 0);
+ SecondLevelPagingEntry = CreateSecondLevelPagingEntry (VtdIndex, 0, mVtdUnitInformation[VtdIndex].Is5LevelPaging);
DEBUG ((DEBUG_VERBOSE,"SecondLevelPagingEntry - 0x%x (S%04x B%02x D%02x F%02x) New\n", SecondLevelPagingEntry, Segment, SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.Function));
Pt = (UINT64)RShiftU64 ((UINT64)(UINTN)SecondLevelPagingEntry, 12);
@@ -922,7 +1041,7 @@ SetAccessAttribute (
ExtContextEntry->Bits.DomainIdentifier = DomainIdentifier;
ExtContextEntry->Bits.Present = 1;
FlushPageTableMemory (VtdIndex, (UINTN)ExtContextEntry, sizeof(*ExtContextEntry));
- DumpDmarExtContextEntryTable (mVtdUnitInformation[VtdIndex].ExtRootEntryTable);
+ DumpDmarExtContextEntryTable (mVtdUnitInformation[VtdIndex].ExtRootEntryTable, mVtdUnitInformation[VtdIndex].Is5LevelPaging);
mVtdUnitInformation[VtdIndex].HasDirtyContext = TRUE;
} else {
SecondLevelPagingEntry = (VOID *)(UINTN)VTD_64BITS_ADDRESS(ExtContextEntry->Bits.SecondLevelPageTranslationPointerLo, ExtContextEntry->Bits.SecondLevelPageTranslationPointerHi);
@@ -930,7 +1049,7 @@ SetAccessAttribute (
}
} else if (ContextEntry != NULL) {
if (ContextEntry->Bits.Present == 0) {
- SecondLevelPagingEntry = CreateSecondLevelPagingEntry (VtdIndex, 0);
+ SecondLevelPagingEntry = CreateSecondLevelPagingEntry (VtdIndex, 0, mVtdUnitInformation[VtdIndex].Is5LevelPaging);
DEBUG ((DEBUG_VERBOSE,"SecondLevelPagingEntry - 0x%x (S%04x B%02x D%02x F%02x) New\n", SecondLevelPagingEntry, Segment, SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.Function));
Pt = (UINT64)RShiftU64 ((UINT64)(UINTN)SecondLevelPagingEntry, 12);
@@ -939,7 +1058,7 @@ SetAccessAttribute (
ContextEntry->Bits.DomainIdentifier = DomainIdentifier;
ContextEntry->Bits.Present = 1;
FlushPageTableMemory (VtdIndex, (UINTN)ContextEntry, sizeof(*ContextEntry));
- DumpDmarContextEntryTable (mVtdUnitInformation[VtdIndex].RootEntryTable);
+ DumpDmarContextEntryTable (mVtdUnitInformation[VtdIndex].RootEntryTable, mVtdUnitInformation[VtdIndex].Is5LevelPaging);
mVtdUnitInformation[VtdIndex].HasDirtyContext = TRUE;
} else {
SecondLevelPagingEntry = (VOID *)(UINTN)VTD_64BITS_ADDRESS(ContextEntry->Bits.SecondLevelPageTranslationPointerLo, ContextEntry->Bits.SecondLevelPageTranslationPointerHi);
@@ -1000,7 +1119,7 @@ AlwaysEnablePageAttribute (
if (mVtdUnitInformation[VtdIndex].FixedSecondLevelPagingEntry == 0) {
DEBUG((DEBUG_INFO, "CreateSecondLevelPagingEntry - %d\n", VtdIndex));
- mVtdUnitInformation[VtdIndex].FixedSecondLevelPagingEntry = CreateSecondLevelPagingEntry (VtdIndex, EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);
+ mVtdUnitInformation[VtdIndex].FixedSecondLevelPagingEntry = CreateSecondLevelPagingEntry (VtdIndex, EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE, mVtdUnitInformation[VtdIndex].Is5LevelPaging);
}
SecondLevelPagingEntry = mVtdUnitInformation[VtdIndex].FixedSecondLevelPagingEntry;
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTableEx.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTableEx.c
index 0ed9e3ca..3918eeee 100644
--- a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTableEx.c
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTableEx.c
@@ -78,11 +78,32 @@ CreateExtContextEntry (
DEBUG ((DEBUG_INFO,"DOMAIN: S%04x, B%02x D%02x F%02x\n", mVtdUnitInformation[VtdIndex].Segment, SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.Function));
- if ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW & BIT2) == 0) {
- DEBUG((DEBUG_ERROR, "!!!! 4-level page-table is not supported on VTD %d !!!!\n", VtdIndex));
+ mVtdUnitInformation[VtdIndex].Is5LevelPaging = FALSE;
+ if ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW & BIT3) != 0) {
+ if ((PcdGet8(PcdVTdPolicyPropertyMask) & BIT3) != 0) {
+ DEBUG((DEBUG_ERROR, "Force to use 4-level page-table on VTD %d\n", VtdIndex));
+ ExtContextEntry->Bits.AddressWidth = 0x2;
+ } if ((PcdGet8(PcdVTdPolicyPropertyMask) & BIT4) != 0) {
+ DEBUG((DEBUG_ERROR, "Force to use 5-level page-table on VTD %d\n", VtdIndex));
+ ExtContextEntry->Bits.AddressWidth = 0x3;
+ mVtdUnitInformation[VtdIndex].Is5LevelPaging = TRUE;
+ } else {
+ if (mAcpiDmarTable->HostAddressWidth > 48) {
+ DEBUG((DEBUG_ERROR, "Using 5-level page-table on VTD %d\n", VtdIndex));
+ ExtContextEntry->Bits.AddressWidth = 0x3;
+ mVtdUnitInformation[VtdIndex].Is5LevelPaging = TRUE;
+ } else {
+ DEBUG((DEBUG_ERROR, "Using 4-level page-table on VTD %d\n", VtdIndex));
+ ExtContextEntry->Bits.AddressWidth = 0x2;
+ }
+ }
+ } else if ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW & BIT2) != 0) {
+ DEBUG((DEBUG_ERROR, "Using 4-level page-table on VTD %d\n", VtdIndex));
+ ExtContextEntry->Bits.AddressWidth = 0x2;
+ } else {
+ DEBUG((DEBUG_ERROR, "!!!! Page-table type is not supported on VTD %d !!!!\n", VtdIndex));
return EFI_UNSUPPORTED;
}
- ExtContextEntry->Bits.AddressWidth = 0x2;
}
FlushPageTableMemory (VtdIndex, (UINTN)mVtdUnitInformation[VtdIndex].ExtRootEntryTable, EFI_PAGES_TO_SIZE(EntryTablePages));
@@ -93,11 +114,13 @@ CreateExtContextEntry (
/**
Dump DMAR extended context entry table.
- @param[in] ExtRootEntry DMAR extended root entry.
+ @param[in] ExtRootEntry DMAR extended root entry.
+ @param[in] Is5LevelPaging If it is the 5 level paging.
**/
VOID
DumpDmarExtContextEntryTable (
- IN VTD_EXT_ROOT_ENTRY *ExtRootEntry
+ IN VTD_EXT_ROOT_ENTRY *ExtRootEntry,
+ IN BOOLEAN Is5LevelPaging
)
{
UINTN Index;
@@ -127,7 +150,7 @@ DumpDmarExtContextEntryTable (
if (ExtContextEntry[Index2].Bits.Present == 0) {
continue;
}
- DumpSecondLevelPagingEntry ((VOID *)(UINTN)VTD_64BITS_ADDRESS(ExtContextEntry[Index2].Bits.SecondLevelPageTranslationPointerLo, ExtContextEntry[Index2].Bits.SecondLevelPageTranslationPointerHi));
+ DumpSecondLevelPagingEntry ((VOID *)(UINTN)VTD_64BITS_ADDRESS(ExtContextEntry[Index2].Bits.SecondLevelPageTranslationPointerLo, ExtContextEntry[Index2].Bits.SecondLevelPageTranslationPointerHi), Is5LevelPaging);
}
if (ExtRootEntry[Index].Bits.UpperPresent == 0) {
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/VtdReg.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/VtdReg.c
index 699639ba..686d235f 100644
--- a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/VtdReg.c
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/VtdReg.c
@@ -174,8 +174,14 @@ PrepareVtdConfig (
if ((mVtdUnitInformation[Index].CapReg.Bits.SLLPS & BIT0) == 0) {
DEBUG((DEBUG_WARN, "!!!! 2MB super page is not supported on VTD %d !!!!\n", Index));
}
- if ((mVtdUnitInformation[Index].CapReg.Bits.SAGAW & BIT2) == 0) {
- DEBUG((DEBUG_ERROR, "!!!! 4-level page-table is not supported on VTD %d !!!!\n", Index));
+ if ((mVtdUnitInformation[Index].CapReg.Bits.SAGAW & BIT3) != 0) {
+ DEBUG((DEBUG_INFO, "Support 5-level page-table on VTD %d\n", Index));
+ }
+ if ((mVtdUnitInformation[Index].CapReg.Bits.SAGAW & BIT2) != 0) {
+ DEBUG((DEBUG_INFO, "Support 4-level page-table on VTD %d\n", Index));
+ }
+ if ((mVtdUnitInformation[Index].CapReg.Bits.SAGAW & (BIT3 | BIT2)) == 0) {
+ DEBUG((DEBUG_ERROR, "!!!! Page-table type 0x%X is not supported on VTD %d !!!!\n", Index, mVtdUnitInformation[Index].CapReg.Bits.SAGAW));
return ;
}
diff --git a/Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dec b/Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dec
index 284820af..8f1edfe2 100644
--- a/Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dec
+++ b/Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dec
@@ -95,6 +95,9 @@
# BIT0: Enable IOMMU during boot (If DMAR table is installed in DXE. If VTD_INFO_PPI is installed in PEI.)
# BIT1: Enable IOMMU when transfer control to OS (ExitBootService in normal boot. EndOfPEI in S3)
# BIT2: Force no IOMMU access attribute request recording before DMAR table is installed.
+ # BIT3: Force to use 4 level paging.
+ # BIT4: If iommu support 5 level paging, force to use 5 level paging.
+ # (If both BIT3 and BIT4 are set, force to use 4 level paging.)
# @Prompt The policy for VTd driver behavior.
gIntelSiliconPkgTokenSpaceGuid.PcdVTdPolicyPropertyMask|1|UINT8|0x00000002
--
2.16.2.windows.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH v3] IntelSiliconPkg/VTd: Add iommu 5 level paging support
2020-11-18 2:33 ` Sheng Wei
@ 2020-11-18 2:49 ` Yao, Jiewen
[not found] ` <16487A52A9CBAF90.960@groups.io>
1 sibling, 0 replies; 6+ messages in thread
From: Yao, Jiewen @ 2020-11-18 2:49 UTC (permalink / raw)
To: Sheng, W, devel@edk2.groups.io
Cc: Ni, Ray, Chaganty, Rangasai V, Huang, Jenny
Sorry I did not say clearly.
1) I mean the (SAGAW & BIT2) check should also happen inside of (SAGAW & BIT3), the first if.
Otherwise, the logic is:
If (5 level support) {
If (need 4 level) {
Do 4 level
}
}
That is odd.
2) In general, I recommend we have a better way to manage test/debug code into production. The PCD should be used when it is absolutely necessary.
I think the policy should be as simple as possible. Otherwise, the production team wont know how to choose.
> -----Original Message-----
> From: Sheng, W <w.sheng@intel.com>
> Sent: Wednesday, November 18, 2020 10:33 AM
> To: Yao, Jiewen <jiewen.yao@intel.com>; devel@edk2.groups.io
> Cc: Ni, Ray <ray.ni@intel.com>; Chaganty, Rangasai V
> <rangasai.v.chaganty@intel.com>; Huang, Jenny <jenny.huang@intel.com>
> Subject: RE: [PATCH v3] IntelSiliconPkg/VTd: Add iommu 5 level paging
> support
>
> Hi Jeiwen,
> For comment 1:
> The code about (SAGAW & BIT2) is just behand (SAGAW & BIT3)
>
> > > + DEBUG((DEBUG_ERROR, "Using 4-level page-table on VTD %d\n",
> > > VtdIndex));
> > > + ExtContextEntry->Bits.AddressWidth = 0x2;
> > > + }
> > > + }
> > > + } else if ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW &
> > > + BIT2) !=
> > > 0) {
> > > + DEBUG((DEBUG_ERROR, "Using 4-level page-table on VTD %d\n",
> > > VtdIndex));
> > > + ExtContextEntry->Bits.AddressWidth = 0x2;
> > > + } else {
> > > + DEBUG((DEBUG_ERROR, "!!!! Page-table type is not supported on
> > > VTD %d !!!!\n", VtdIndex));
> > > return EFI_UNSUPPORTED;
> > > }
> > > - ExtContextEntry->Bits.AddressWidth = 0x2;
> > > }
>
> For comment 2:
> > # BIT3: Force to use 4 level paging.
> > # BIT4: If iommu support 5 level paging, force to use 5 level paging.
> > # (If both BIT3 and BIT4 are set, force to use 4 level paging.)
> Mostly, these 2 bits are for debug/test purpose, it could be used to force the
> page table depth.
> Do you think it is no necessary? Or we could find another solution ?
>
> Thank you
> BR
> Sheng Wei
>
>
> > -----Original Message-----
> > From: Yao, Jiewen <jiewen.yao@intel.com>
> > Sent: 2020年11月18日 9:39
> > To: Sheng, W <w.sheng@intel.com>; devel@edk2.groups.io
> > Cc: Ni, Ray <ray.ni@intel.com>; Chaganty, Rangasai V
> > <rangasai.v.chaganty@intel.com>; Huang, Jenny <jenny.huang@intel.com>
> > Subject: RE: [PATCH v3] IntelSiliconPkg/VTd: Add iommu 5 level paging
> support
> >
> > Hi
> > I have 2 comments:
> >
> > 1) below capability check seems not correct.
> >
> > (SAGAW & BIT3) is for 5 level only.
> > We need check (SAGAW & BIT2) for 4 level. But I do not see the code. Do I
> miss
> > something?
> >
> > if ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW & BIT3) != 0) {
> > if ((PcdGet8(PcdVTdPolicyPropertyMask) & BIT3) != 0) {
> > DEBUG((DEBUG_ERROR, "Force to use 4-level page-table on
> VTD %d\n",
> > VtdIndex));
> > ContextEntry->Bits.AddressWidth = 0x2;
> > } if ((PcdGet8(PcdVTdPolicyPropertyMask) & BIT4) != 0) {
> > DEBUG((DEBUG_ERROR, "Force to use 5-level page-table on
> VTD %d\n",
> > VtdIndex));
> > ContextEntry->Bits.AddressWidth = 0x3;
> > mVtdUnitInformation[VtdIndex].Is5LevelPaging = TRUE;
> > } else {
> > if (mAcpiDmarTable->HostAddressWidth > 48) {
> > DEBUG((DEBUG_ERROR, "Using 5-level page-table on VTD %d\n",
> > VtdIndex));
> > ContextEntry->Bits.AddressWidth = 0x3;
> > mVtdUnitInformation[VtdIndex].Is5LevelPaging = TRUE;
> > } else {
> > DEBUG((DEBUG_ERROR, "Using 4-level page-table on VTD %d\n",
> > VtdIndex));
> > ContextEntry->Bits.AddressWidth = 0x2;
> > }
> > }
> >
> > 2) I am wondering, do we really need 2 bit for level selection ?
> > What if force 4 level, but the platform does not support?
> > What if force 5 level, but the platform does not support?
> >
> > # BIT3: Force to use 4 level paging.
> > # BIT4: If iommu support 5 level paging, force to use 5 level paging.
> > # (If both BIT3 and BIT4 are set, force to use 4 level paging.)
> >
> >
> gIntelSiliconPkgTokenSpaceGuid.PcdVTdPolicyPropertyMask|1|UINT8|0x000
> 00
> > 002
> >
> > Can we align the solution in DXE/SMM paging solution?
> >
> >
> >
> > > -----Original Message-----
> > > From: Sheng, W <w.sheng@intel.com>
> > > Sent: Wednesday, November 18, 2020 9:18 AM
> > > To: devel@edk2.groups.io
> > > Cc: Ni, Ray <ray.ni@intel.com>; Chaganty, Rangasai V
> > > <rangasai.v.chaganty@intel.com>; Yao, Jiewen <jiewen.yao@intel.com>;
> > > Huang, Jenny <jenny.huang@intel.com>
> > > Subject: [PATCH v3] IntelSiliconPkg/VTd: Add iommu 5 level paging
> > > support
> > >
> > > Support iommu 5 level paging for translation table.
> > >
> > > REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3067
> > >
> > > 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: Jiewen Yao <jiewen.yao@intel.com>
> > > Cc: Jenny Huang <jenny.huang@intel.com>
> > > ---
> > > .../Feature/VTd/IntelVTdDxe/DmaProtection.c | 4 +-
> > > .../Feature/VTd/IntelVTdDxe/DmaProtection.h | 19 +-
> > > .../Feature/VTd/IntelVTdDxe/TranslationTable.c | 287
> +++++++++++++++--
> > > ----
> > > .../Feature/VTd/IntelVTdDxe/TranslationTableEx.c | 35 ++-
> > > .../Feature/VTd/IntelVTdDxe/VtdReg.c | 10 +-
> > > Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dec | 3 +
> > > 6 files changed, 258 insertions(+), 100 deletions(-)
> > >
> > > diff --git
> > > a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.
> > > c
> > > b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.
> > > c
> > > index 9b6135ef..628565ee 100644
> > > ---
> > > a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.
> > > c
> > > +++
> > > b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.
> > > c
> > > @@ -523,10 +523,10 @@ SetupVtd (
> > > for (Index = 0; Index < mVtdUnitNumber; Index++) {
> > > DEBUG ((DEBUG_INFO,"VTD Unit %d (Segment: %04x)\n", Index,
> > > mVtdUnitInformation[Index].Segment));
> > > if (mVtdUnitInformation[Index].ExtRootEntryTable != NULL) {
> > > - DumpDmarExtContextEntryTable
> > > (mVtdUnitInformation[Index].ExtRootEntryTable);
> > > + DumpDmarExtContextEntryTable
> > > (mVtdUnitInformation[Index].ExtRootEntryTable,
> > > mVtdUnitInformation[Index].Is5LevelPaging);
> > > }
> > > if (mVtdUnitInformation[Index].RootEntryTable != NULL) {
> > > - DumpDmarContextEntryTable
> > > (mVtdUnitInformation[Index].RootEntryTable);
> > > + DumpDmarContextEntryTable
> > > (mVtdUnitInformation[Index].RootEntryTable,
> > > mVtdUnitInformation[Index].Is5LevelPaging);
> > > }
> > > }
> > >
> > > diff --git
> > > a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.
> > > h
> > > b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.
> > > h
> > > index a3331db8..f641cea0 100644
> > > ---
> > > a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.
> > > h
> > > +++
> > > b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.
> > > h
> > > @@ -77,6 +77,7 @@ typedef struct {
> > > BOOLEAN HasDirtyContext;
> > > BOOLEAN HasDirtyPages;
> > > PCI_DEVICE_INFORMATION PciDeviceInfo;
> > > + BOOLEAN Is5LevelPaging;
> > > } VTD_UNIT_INFORMATION;
> > >
> > > //
> > > @@ -375,31 +376,37 @@ ParseDmarAcpiTableRmrr (
> > > /**
> > > Dump DMAR context entry table.
> > >
> > > - @param[in] RootEntry DMAR root entry.
> > > + @param[in] RootEntry DMAR root entry.
> > > + @param[in] Is5LevelPaging If it is the 5 level paging.
> > > **/
> > > VOID
> > > DumpDmarContextEntryTable (
> > > - IN VTD_ROOT_ENTRY *RootEntry
> > > + IN VTD_ROOT_ENTRY *RootEntry,
> > > + IN BOOLEAN Is5LevelPaging
> > > );
> > >
> > > /**
> > > Dump DMAR extended context entry table.
> > >
> > > - @param[in] ExtRootEntry DMAR extended root entry.
> > > + @param[in] ExtRootEntry DMAR extended root entry.
> > > + @param[in] Is5LevelPaging If it is the 5 level paging.
> > > **/
> > > VOID
> > > DumpDmarExtContextEntryTable (
> > > - IN VTD_EXT_ROOT_ENTRY *ExtRootEntry
> > > + IN VTD_EXT_ROOT_ENTRY *ExtRootEntry, IN BOOLEAN Is5LevelPaging
> > > );
> > >
> > > /**
> > > Dump DMAR second level paging entry.
> > >
> > > - @param[in] SecondLevelPagingEntry The second level paging entry.
> > > + @param[in] SecondLevelPagingEntry The second level paging entry.
> > > + @param[in] Is5LevelPaging If it is the 5 level paging.
> > > **/
> > > VOID
> > > DumpSecondLevelPagingEntry (
> > > - IN VOID *SecondLevelPagingEntry
> > > + IN VOID *SecondLevelPagingEntry,
> > > + IN BOOLEAN Is5LevelPaging
> > > );
> > >
> > > /**
> > > diff --git
> > > a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTab
> > > le.c
> > > b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTab
> > > le.c
> > > index 201d663d..cb59860a 100644
> > > ---
> > > a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTab
> > > le.c
> > > +++
> > > b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTab
> > > le.c @@ -128,11 +128,32 @@ CreateContextEntry (
> > >
> > > DEBUG ((DEBUG_INFO,"Source: S%04x B%02x D%02x F%02x\n",
> > > mVtdUnitInformation[VtdIndex].Segment, SourceId.Bits.Bus,
> > > SourceId.Bits.Device, SourceId.Bits.Function));
> > >
> > > - if ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW & BIT2) == 0)
> {
> > > - DEBUG((DEBUG_ERROR, "!!!! 4-level page-table is not supported on
> > > VTD %d !!!!\n", VtdIndex));
> > > + mVtdUnitInformation[VtdIndex].Is5LevelPaging = FALSE;
> > > + if ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW & BIT3) != 0)
> {
> > > + if ((PcdGet8(PcdVTdPolicyPropertyMask) & BIT3) != 0) {
> > > + DEBUG((DEBUG_ERROR, "Force to use 4-level page-table on VTD
> > > + %d\n",
> > > VtdIndex));
> > > + ContextEntry->Bits.AddressWidth = 0x2;
> > > + } if ((PcdGet8(PcdVTdPolicyPropertyMask) & BIT4) != 0) {
> > > + DEBUG((DEBUG_ERROR, "Force to use 5-level page-table on VTD
> > > + %d\n",
> > > VtdIndex));
> > > + ContextEntry->Bits.AddressWidth = 0x3;
> > > + mVtdUnitInformation[VtdIndex].Is5LevelPaging = TRUE;
> > > + } else {
> > > + if (mAcpiDmarTable->HostAddressWidth > 48) {
> > > + DEBUG((DEBUG_ERROR, "Using 5-level page-table on VTD %d\n",
> > > VtdIndex));
> > > + ContextEntry->Bits.AddressWidth = 0x3;
> > > + mVtdUnitInformation[VtdIndex].Is5LevelPaging = TRUE;
> > > + } else {
> > > + DEBUG((DEBUG_ERROR, "Using 4-level page-table on VTD %d\n",
> > > VtdIndex));
> > > + ContextEntry->Bits.AddressWidth = 0x2;
> > > + }
> > > + }
> > > + } else if ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW &
> > > + BIT2) !=
> > > 0) {
> > > + DEBUG((DEBUG_ERROR, "Using 4-level page-table on VTD %d\n",
> > > VtdIndex));
> > > + ContextEntry->Bits.AddressWidth = 0x2;
> > > + } else {
> > > + DEBUG((DEBUG_ERROR, "!!!! Page-table type is not supported on
> > > VTD %d !!!!\n", VtdIndex));
> > > return EFI_UNSUPPORTED;
> > > }
> > > - ContextEntry->Bits.AddressWidth = 0x2;
> > > }
> > >
> > > FlushPageTableMemory (VtdIndex,
> > > (UINTN)mVtdUnitInformation[VtdIndex].RootEntryTable,
> > > EFI_PAGES_TO_SIZE(EntryTablePages));
> > > @@ -148,6 +169,7 @@ CreateContextEntry (
> > > @param[in] MemoryBase The base of the memory.
> > > @param[in] MemoryLimit The limit of the memory.
> > > @param[in] IoMmuAccess The IOMMU access.
> > > + @param[in] Is5LevelPaging If it is the 5 level paging.
> > >
> > > @return The second level paging entry.
> > > **/
> > > @@ -157,16 +179,23 @@ CreateSecondLevelPagingEntryTable (
> > > IN VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry,
> > > IN UINT64 MemoryBase,
> > > IN UINT64 MemoryLimit,
> > > - IN UINT64 IoMmuAccess
> > > + IN UINT64 IoMmuAccess,
> > > + IN BOOLEAN Is5LevelPaging
> > > )
> > > {
> > > + UINTN Index5;
> > > UINTN Index4;
> > > UINTN Index3;
> > > UINTN Index2;
> > > + UINTN Lvl5Start;
> > > + UINTN Lvl5End;
> > > + UINTN Lvl4PagesStart;
> > > + UINTN Lvl4PagesEnd;
> > > UINTN Lvl4Start;
> > > UINTN Lvl4End;
> > > UINTN Lvl3Start;
> > > UINTN Lvl3End;
> > > + VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl5PtEntry;
> > > VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl4PtEntry;
> > > VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl3PtEntry;
> > > VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl2PtEntry; @@ -184,7 +213,7
> > @@
> > > CreateSecondLevelPagingEntryTable (
> > > if (SecondLevelPagingEntry == NULL) {
> > > SecondLevelPagingEntry = AllocateZeroPages (1);
> > > if (SecondLevelPagingEntry == NULL) {
> > > - DEBUG ((DEBUG_ERROR,"Could not Alloc LVL4 PT. \n"));
> > > + DEBUG ((DEBUG_ERROR,"Could not Alloc LVL4 or LVL5 PT. \n"));
> > > return NULL;
> > > }
> > > FlushPageTableMemory (VtdIndex, (UINTN)SecondLevelPagingEntry,
> > > EFI_PAGES_TO_SIZE(1)); @@ -197,66 +226,109 @@
> > > CreateSecondLevelPagingEntryTable (
> > > return SecondLevelPagingEntry;
> > > }
> > >
> > > - Lvl4Start = RShiftU64 (BaseAddress, 39) & 0x1FF;
> > > - Lvl4End = RShiftU64 (EndAddress - 1, 39) & 0x1FF;
> > > + if (Is5LevelPaging) {
> > > + Lvl5Start = RShiftU64 (BaseAddress, 48) & 0x1FF;
> > > + Lvl5End = RShiftU64 (EndAddress - 1, 48) & 0x1FF;
> > > + DEBUG ((DEBUG_INFO," Lvl5Start - 0x%x, Lvl5End - 0x%x\n",
> > > + Lvl5Start,
> > > Lvl5End));
> > >
> > > - DEBUG ((DEBUG_INFO," Lvl4Start - 0x%x, Lvl4End - 0x%x\n",
> > > Lvl4Start, Lvl4End));
> > > + Lvl4Start = RShiftU64 (BaseAddress, 39) & 0x1FF;
> > > + Lvl4End = RShiftU64 (EndAddress - 1, 39) & 0x1FF;
> > >
> > > - Lvl4PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> > > *)SecondLevelPagingEntry;
> > > - for (Index4 = Lvl4Start; Index4 <= Lvl4End; Index4++) {
> > > - if (Lvl4PtEntry[Index4].Uint64 == 0) {
> > > - Lvl4PtEntry[Index4].Uint64 = (UINT64)(UINTN)AllocateZeroPages (1);
> > > - if (Lvl4PtEntry[Index4].Uint64 == 0) {
> > > - DEBUG ((DEBUG_ERROR,"!!!!!! ALLOCATE LVL4 PAGE FAIL
> > > (0x%x)!!!!!!\n", Index4));
> > > - ASSERT(FALSE);
> > > - return NULL;
> > > - }
> > > - FlushPageTableMemory (VtdIndex,
> (UINTN)Lvl4PtEntry[Index4].Uint64,
> > > SIZE_4KB);
> > > - SetSecondLevelPagingEntryAttribute (&Lvl4PtEntry[Index4],
> > > EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);
> > > - }
> > > + Lvl4PagesStart = (Lvl5Start<<9) | Lvl4Start;
> > > + Lvl4PagesEnd = (Lvl5End<<9) | Lvl4End;
> > > + DEBUG ((DEBUG_INFO," Lvl4PagesStart - 0x%x, Lvl4PagesEnd -
> > > + 0x%x\n",
> > > Lvl4PagesStart, Lvl4PagesEnd));
> > >
> > > - Lvl3Start = RShiftU64 (BaseAddress, 30) & 0x1FF;
> > > - if (ALIGN_VALUE_LOW(BaseAddress + SIZE_1GB, SIZE_1GB) <=
> > > EndAddress) {
> > > - Lvl3End = SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY) - 1;
> > > - } else {
> > > - Lvl3End = RShiftU64 (EndAddress - 1, 30) & 0x1FF;
> > > + Lvl5PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> > > *)SecondLevelPagingEntry;
> > > + } else {
> > > + Lvl5Start = RShiftU64 (BaseAddress, 48) & 0x1FF;
> > > + Lvl5End = Lvl5Start;
> > > +
> > > + Lvl4Start = RShiftU64 (BaseAddress, 39) & 0x1FF;
> > > + Lvl4End = RShiftU64 (EndAddress - 1, 39) & 0x1FF;
> > > + DEBUG ((DEBUG_INFO," Lvl4Start - 0x%x, Lvl4End - 0x%x\n",
> > > + Lvl4Start,
> > > Lvl4End));
> > > +
> > > + Lvl4PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> > > *)SecondLevelPagingEntry;
> > > + }
> > > +
> > > + for (Index5 = Lvl5Start; Index5 <= Lvl5End; Index5++) {
> > > + if (Is5LevelPaging) {
> > > + if (Lvl5PtEntry[Index5].Uint64 == 0) {
> > > + Lvl5PtEntry[Index5].Uint64 = (UINT64)(UINTN)AllocateZeroPages (1);
> > > + if (Lvl5PtEntry[Index5].Uint64 == 0) {
> > > + DEBUG ((DEBUG_ERROR,"!!!!!! ALLOCATE LVL4 PAGE FAIL
> > > (0x%x)!!!!!!\n", Index5));
> > > + ASSERT(FALSE);
> > > + return NULL;
> > > + }
> > > + FlushPageTableMemory (VtdIndex,
> > > + (UINTN)Lvl5PtEntry[Index5].Uint64,
> > > SIZE_4KB);
> > > + SetSecondLevelPagingEntryAttribute (&Lvl5PtEntry[Index5],
> > > EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);
> > > + }
> > > + Lvl4Start = Lvl4PagesStart & 0x1FF;
> > > + if (((Index5+1)<<9) > Lvl4PagesEnd) {
> > > + Lvl4End = SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY) -
> 1;;
> > > + Lvl4PagesStart = (Index5+1)<<9;
> > > + } else {
> > > + Lvl4End = Lvl4PagesEnd & 0x1FF;
> > > + }
> > > + DEBUG ((DEBUG_INFO," Lvl5(0x%x): Lvl4Start - 0x%x, Lvl4End -
> > > + 0x%x\n",
> > > Index5, Lvl4Start, Lvl4End));
> > > + Lvl4PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> > > *)(UINTN)VTD_64BITS_ADDRESS(Lvl5PtEntry[Index5].Bits.AddressLo,
> > > Lvl5PtEntry[Index5].Bits.AddressHi);
> > > }
> > > - DEBUG ((DEBUG_INFO," Lvl4(0x%x): Lvl3Start - 0x%x, Lvl3End -
> 0x%x\n",
> > > Index4, Lvl3Start, Lvl3End));
> > >
> > > - Lvl3PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> > > *)(UINTN)VTD_64BITS_ADDRESS(Lvl4PtEntry[Index4].Bits.AddressLo,
> > > Lvl4PtEntry[Index4].Bits.AddressHi);
> > > - for (Index3 = Lvl3Start; Index3 <= Lvl3End; Index3++) {
> > > - if (Lvl3PtEntry[Index3].Uint64 == 0) {
> > > - Lvl3PtEntry[Index3].Uint64 = (UINT64)(UINTN)AllocateZeroPages (1);
> > > - if (Lvl3PtEntry[Index3].Uint64 == 0) {
> > > - DEBUG ((DEBUG_ERROR,"!!!!!! ALLOCATE LVL3 PAGE FAIL (0x%x,
> > > 0x%x)!!!!!!\n", Index4, Index3));
> > > + for (Index4 = Lvl4Start; Index4 <= Lvl4End; Index4++) {
> > > + if (Lvl4PtEntry[Index4].Uint64 == 0) {
> > > + Lvl4PtEntry[Index4].Uint64 = (UINT64)(UINTN)AllocateZeroPages (1);
> > > + if (Lvl4PtEntry[Index4].Uint64 == 0) {
> > > + DEBUG ((DEBUG_ERROR,"!!!!!! ALLOCATE LVL4 PAGE FAIL
> > > (0x%x)!!!!!!\n", Index4));
> > > ASSERT(FALSE);
> > > return NULL;
> > > }
> > > - FlushPageTableMemory (VtdIndex,
> (UINTN)Lvl3PtEntry[Index3].Uint64,
> > > SIZE_4KB);
> > > - SetSecondLevelPagingEntryAttribute (&Lvl3PtEntry[Index3],
> > > EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);
> > > + FlushPageTableMemory (VtdIndex,
> > > + (UINTN)Lvl4PtEntry[Index4].Uint64,
> > > SIZE_4KB);
> > > + SetSecondLevelPagingEntryAttribute (&Lvl4PtEntry[Index4],
> > > EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);
> > > }
> > >
> > > - Lvl2PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> > > *)(UINTN)VTD_64BITS_ADDRESS(Lvl3PtEntry[Index3].Bits.AddressLo,
> > > Lvl3PtEntry[Index3].Bits.AddressHi);
> > > - for (Index2 = 0; Index2 <
> > > SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY); Index2++) {
> > > - Lvl2PtEntry[Index2].Uint64 = BaseAddress;
> > > - SetSecondLevelPagingEntryAttribute (&Lvl2PtEntry[Index2],
> > > IoMmuAccess);
> > > - Lvl2PtEntry[Index2].Bits.PageSize = 1;
> > > - BaseAddress += SIZE_2MB;
> > > + Lvl3Start = RShiftU64 (BaseAddress, 30) & 0x1FF;
> > > + if (ALIGN_VALUE_LOW(BaseAddress + SIZE_1GB, SIZE_1GB) <=
> > > EndAddress) {
> > > + Lvl3End = SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY) - 1;
> > > + } else {
> > > + Lvl3End = RShiftU64 (EndAddress - 1, 30) & 0x1FF;
> > > + }
> > > + DEBUG ((DEBUG_INFO," Lvl4(0x%x): Lvl3Start - 0x%x, Lvl3End -
> > > + 0x%x\n",
> > > Index4, Lvl3Start, Lvl3End));
> > > +
> > > + Lvl3PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> > > *)(UINTN)VTD_64BITS_ADDRESS(Lvl4PtEntry[Index4].Bits.AddressLo,
> > > Lvl4PtEntry[Index4].Bits.AddressHi);
> > > + for (Index3 = Lvl3Start; Index3 <= Lvl3End; Index3++) {
> > > + if (Lvl3PtEntry[Index3].Uint64 == 0) {
> > > + Lvl3PtEntry[Index3].Uint64 = (UINT64)(UINTN)AllocateZeroPages
> (1);
> > > + if (Lvl3PtEntry[Index3].Uint64 == 0) {
> > > + DEBUG ((DEBUG_ERROR,"!!!!!! ALLOCATE LVL3 PAGE FAIL
> > > + (0x%x,
> > > 0x%x)!!!!!!\n", Index4, Index3));
> > > + ASSERT(FALSE);
> > > + return NULL;
> > > + }
> > > + FlushPageTableMemory (VtdIndex,
> > > + (UINTN)Lvl3PtEntry[Index3].Uint64,
> > > SIZE_4KB);
> > > + SetSecondLevelPagingEntryAttribute (&Lvl3PtEntry[Index3],
> > > EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);
> > > + }
> > > +
> > > + Lvl2PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> > > *)(UINTN)VTD_64BITS_ADDRESS(Lvl3PtEntry[Index3].Bits.AddressLo,
> > > Lvl3PtEntry[Index3].Bits.AddressHi);
> > > + for (Index2 = 0; Index2 <
> > > SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY); Index2++) {
> > > + Lvl2PtEntry[Index2].Uint64 = BaseAddress;
> > > + SetSecondLevelPagingEntryAttribute (&Lvl2PtEntry[Index2],
> > > IoMmuAccess);
> > > + Lvl2PtEntry[Index2].Bits.PageSize = 1;
> > > + BaseAddress += SIZE_2MB;
> > > + if (BaseAddress >= MemoryLimit) {
> > > + break;
> > > + }
> > > + }
> > > + FlushPageTableMemory (VtdIndex, (UINTN)Lvl2PtEntry,
> > > + SIZE_4KB);
> > > if (BaseAddress >= MemoryLimit) {
> > > break;
> > > }
> > > }
> > > - FlushPageTableMemory (VtdIndex, (UINTN)Lvl2PtEntry, SIZE_4KB);
> > > + FlushPageTableMemory (VtdIndex, (UINTN)&Lvl3PtEntry[Lvl3Start],
> > > (UINTN)&Lvl3PtEntry[Lvl3End + 1] - (UINTN)&Lvl3PtEntry[Lvl3Start]);
> > > if (BaseAddress >= MemoryLimit) {
> > > break;
> > > }
> > > }
> > > - FlushPageTableMemory (VtdIndex, (UINTN)&Lvl3PtEntry[Lvl3Start],
> > > (UINTN)&Lvl3PtEntry[Lvl3End + 1] - (UINTN)&Lvl3PtEntry[Lvl3Start]);
> > > - if (BaseAddress >= MemoryLimit) {
> > > - break;
> > > - }
> > > + FlushPageTableMemory (VtdIndex, (UINTN)&Lvl4PtEntry[Lvl4Start],
> > > (UINTN)&Lvl4PtEntry[Lvl4End + 1] - (UINTN)&Lvl4PtEntry[Lvl4Start]);
> > > }
> > > - FlushPageTableMemory (VtdIndex, (UINTN)&Lvl4PtEntry[Lvl4Start],
> > > (UINTN)&Lvl4PtEntry[Lvl4End + 1] - (UINTN)&Lvl4PtEntry[Lvl4Start]);
> > > + FlushPageTableMemory (VtdIndex, (UINTN)&Lvl5PtEntry[Lvl5Start],
> > > (UINTN)&Lvl5PtEntry[Lvl5End + 1] - (UINTN)&Lvl5PtEntry[Lvl5Start]);
> > >
> > > return SecondLevelPagingEntry;
> > > }
> > > @@ -266,26 +338,28 @@ CreateSecondLevelPagingEntryTable (
> > >
> > > @param[in] VtdIndex The index of the VTd engine.
> > > @param[in] IoMmuAccess The IOMMU access.
> > > + @param[in] Is5LevelPaging If it is the 5 level paging.
> > >
> > > @return The second level paging entry.
> > > **/
> > > VTD_SECOND_LEVEL_PAGING_ENTRY *
> > > CreateSecondLevelPagingEntry (
> > > IN UINTN VtdIndex,
> > > - IN UINT64 IoMmuAccess
> > > + IN UINT64 IoMmuAccess,
> > > + IN BOOLEAN Is5LevelPaging
> > > )
> > > {
> > > VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry;
> > >
> > > SecondLevelPagingEntry = NULL;
> > > - SecondLevelPagingEntry = CreateSecondLevelPagingEntryTable
> > > (VtdIndex, SecondLevelPagingEntry, 0, mBelow4GMemoryLimit,
> > > IoMmuAccess);
> > > + SecondLevelPagingEntry = CreateSecondLevelPagingEntryTable
> > > + (VtdIndex,
> > > SecondLevelPagingEntry, 0, mBelow4GMemoryLimit, IoMmuAccess,
> > > Is5LevelPaging);
> > > if (SecondLevelPagingEntry == NULL) {
> > > return NULL;
> > > }
> > >
> > > if (mAbove4GMemoryLimit != 0) {
> > > ASSERT (mAbove4GMemoryLimit > BASE_4GB);
> > > - SecondLevelPagingEntry = CreateSecondLevelPagingEntryTable
> (VtdIndex,
> > > SecondLevelPagingEntry, SIZE_4GB, mAbove4GMemoryLimit,
> IoMmuAccess);
> > > + SecondLevelPagingEntry = CreateSecondLevelPagingEntryTable
> > > + (VtdIndex,
> > > SecondLevelPagingEntry, SIZE_4GB, mAbove4GMemoryLimit,
> IoMmuAccess,
> > > Is5LevelPaging);
> > > if (SecondLevelPagingEntry == NULL) {
> > > return NULL;
> > > }
> > > @@ -326,11 +400,13 @@ SetupTranslationTable (
> > > /**
> > > Dump DMAR context entry table.
> > >
> > > - @param[in] RootEntry DMAR root entry.
> > > + @param[in] RootEntry DMAR root entry.
> > > + @param[in] Is5LevelPaging If it is the 5 level paging.
> > > **/
> > > VOID
> > > DumpDmarContextEntryTable (
> > > - IN VTD_ROOT_ENTRY *RootEntry
> > > + IN VTD_ROOT_ENTRY *RootEntry,
> > > + IN BOOLEAN Is5LevelPaging
> > > )
> > > {
> > > UINTN Index;
> > > @@ -359,7 +435,7 @@ DumpDmarContextEntryTable (
> > > if (ContextEntry[Index2].Bits.Present == 0) {
> > > continue;
> > > }
> > > - DumpSecondLevelPagingEntry ((VOID
> > >
> *)(UINTN)VTD_64BITS_ADDRESS(ContextEntry[Index2].Bits.SecondLevelPage
> > > TranslationPointerLo,
> > > ContextEntry[Index2].Bits.SecondLevelPageTranslationPointerHi));
> > > + DumpSecondLevelPagingEntry ((VOID
> > >
> *)(UINTN)VTD_64BITS_ADDRESS(ContextEntry[Index2].Bits.SecondLevelPage
> > > TranslationPointerLo,
> > > ContextEntry[Index2].Bits.SecondLevelPageTranslationPointerHi),
> > > Is5LevelPaging);
> > > }
> > > }
> > > DEBUG ((DEBUG_INFO,"=========================\n"));
> > > @@ -368,17 +444,22 @@ DumpDmarContextEntryTable (
> > > /**
> > > Dump DMAR second level paging entry.
> > >
> > > - @param[in] SecondLevelPagingEntry The second level paging entry.
> > > + @param[in] SecondLevelPagingEntry The second level paging entry.
> > > + @param[in] Is5LevelPaging If it is the 5 level paging.
> > > **/
> > > VOID
> > > DumpSecondLevelPagingEntry (
> > > - IN VOID *SecondLevelPagingEntry
> > > + IN VOID *SecondLevelPagingEntry,
> > > + IN BOOLEAN Is5LevelPaging
> > > )
> > > {
> > > + UINTN Index5;
> > > UINTN Index4;
> > > UINTN Index3;
> > > UINTN Index2;
> > > UINTN Index1;
> > > + UINTN Lvl5IndexEnd;
> > > + VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl5PtEntry;
> > > VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl4PtEntry;
> > > VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl3PtEntry;
> > > VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl2PtEntry; @@ -386,38
> +467,53
> > @@
> > > DumpSecondLevelPagingEntry (
> > >
> > > DEBUG ((DEBUG_VERBOSE,"================\n"));
> > > DEBUG ((DEBUG_VERBOSE,"DMAR Second Level Page Table:\n"));
> > > + DEBUG ((DEBUG_VERBOSE,"SecondLevelPagingEntry Base - 0x%x,
> > > Is5LevelPaging - %d\n", SecondLevelPagingEntry, Is5LevelPaging));
> > >
> > > - DEBUG ((DEBUG_VERBOSE,"SecondLevelPagingEntry Base - 0x%x\n",
> > > SecondLevelPagingEntry));
> > > + Lvl5IndexEnd = Is5LevelPaging ?
> > > SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY) : 1;
> > > Lvl4PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> > > *)SecondLevelPagingEntry;
> > > - for (Index4 = 0; Index4 <
> > > SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY); Index4++) {
> > > - if (Lvl4PtEntry[Index4].Uint64 != 0) {
> > > - DEBUG ((DEBUG_VERBOSE," Lvl4Pt Entry(0x%03x) - 0x%016lx\n",
> Index4,
> > > Lvl4PtEntry[Index4].Uint64));
> > > - }
> > > - if (Lvl4PtEntry[Index4].Uint64 == 0) {
> > > - continue;
> > > - }
> > > - Lvl3PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> > > *)(UINTN)VTD_64BITS_ADDRESS(Lvl4PtEntry[Index4].Bits.AddressLo,
> > > Lvl4PtEntry[Index4].Bits.AddressHi);
> > > - for (Index3 = 0; Index3 <
> > > SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY); Index3++) {
> > > - if (Lvl3PtEntry[Index3].Uint64 != 0) {
> > > - DEBUG ((DEBUG_VERBOSE," Lvl3Pt Entry(0x%03x) - 0x%016lx\n",
> > > Index3, Lvl3PtEntry[Index3].Uint64));
> > > + Lvl5PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> > > *)SecondLevelPagingEntry;
> > > +
> > > + for (Index5 = 0; Index5 < Lvl5IndexEnd; Index5++) {
> > > + if (Is5LevelPaging) {
> > > + if (Lvl5PtEntry[Index5].Uint64 != 0) {
> > > + DEBUG ((DEBUG_VERBOSE," Lvl5Pt Entry(0x%03x) - 0x%016lx\n",
> > > Index5, Lvl5PtEntry[Index5].Uint64));
> > > }
> > > - if (Lvl3PtEntry[Index3].Uint64 == 0) {
> > > + if (Lvl5PtEntry[Index5].Uint64 == 0) {
> > > continue;
> > > }
> > > + Lvl4PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> > > *)(UINTN)VTD_64BITS_ADDRESS(Lvl5PtEntry[Index5].Bits.AddressLo,
> > > Lvl5PtEntry[Index5].Bits.AddressHi);
> > > + }
> > >
> > > - Lvl2PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> > > *)(UINTN)VTD_64BITS_ADDRESS(Lvl3PtEntry[Index3].Bits.AddressLo,
> > > Lvl3PtEntry[Index3].Bits.AddressHi);
> > > - for (Index2 = 0; Index2 <
> > > SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY); Index2++) {
> > > - if (Lvl2PtEntry[Index2].Uint64 != 0) {
> > > - DEBUG ((DEBUG_VERBOSE," Lvl2Pt Entry(0x%03x) - 0x%016lx\n",
> > > Index2, Lvl2PtEntry[Index2].Uint64));
> > > + for (Index4 = 0; Index4 <
> > > SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY); Index4++) {
> > > + if (Lvl4PtEntry[Index4].Uint64 != 0) {
> > > + DEBUG ((DEBUG_VERBOSE," Lvl4Pt Entry(0x%03x) - 0x%016lx\n",
> > > Index4, Lvl4PtEntry[Index4].Uint64));
> > > + }
> > > + if (Lvl4PtEntry[Index4].Uint64 == 0) {
> > > + continue;
> > > + }
> > > + Lvl3PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> > > *)(UINTN)VTD_64BITS_ADDRESS(Lvl4PtEntry[Index4].Bits.AddressLo,
> > > Lvl4PtEntry[Index4].Bits.AddressHi);
> > > + for (Index3 = 0; Index3 <
> > > SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY); Index3++) {
> > > + if (Lvl3PtEntry[Index3].Uint64 != 0) {
> > > + DEBUG ((DEBUG_VERBOSE," Lvl3Pt Entry(0x%03x) - 0x%016lx\n",
> > > Index3, Lvl3PtEntry[Index3].Uint64));
> > > }
> > > - if (Lvl2PtEntry[Index2].Uint64 == 0) {
> > > + if (Lvl3PtEntry[Index3].Uint64 == 0) {
> > > continue;
> > > }
> > > - if (Lvl2PtEntry[Index2].Bits.PageSize == 0) {
> > > - Lvl1PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> > > *)(UINTN)VTD_64BITS_ADDRESS(Lvl2PtEntry[Index2].Bits.AddressLo,
> > > Lvl2PtEntry[Index2].Bits.AddressHi);
> > > - for (Index1 = 0; Index1 <
> > > SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY); Index1++) {
> > > - if (Lvl1PtEntry[Index1].Uint64 != 0) {
> > > - DEBUG ((DEBUG_VERBOSE," Lvl1Pt Entry(0x%03x) -
> > 0x%016lx\n",
> > > Index1, Lvl1PtEntry[Index1].Uint64));
> > > +
> > > + Lvl2PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> > > *)(UINTN)VTD_64BITS_ADDRESS(Lvl3PtEntry[Index3].Bits.AddressLo,
> > > Lvl3PtEntry[Index3].Bits.AddressHi);
> > > + for (Index2 = 0; Index2 <
> > > SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY); Index2++) {
> > > + if (Lvl2PtEntry[Index2].Uint64 != 0) {
> > > + DEBUG ((DEBUG_VERBOSE," Lvl2Pt Entry(0x%03x) - 0x%016lx\n",
> > > Index2, Lvl2PtEntry[Index2].Uint64));
> > > + }
> > > + if (Lvl2PtEntry[Index2].Uint64 == 0) {
> > > + continue;
> > > + }
> > > + if (Lvl2PtEntry[Index2].Bits.PageSize == 0) {
> > > + Lvl1PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> > > *)(UINTN)VTD_64BITS_ADDRESS(Lvl2PtEntry[Index2].Bits.AddressLo,
> > > Lvl2PtEntry[Index2].Bits.AddressHi);
> > > + for (Index1 = 0; Index1 <
> > > SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY); Index1++) {
> > > + if (Lvl1PtEntry[Index1].Uint64 != 0) {
> > > + DEBUG ((DEBUG_VERBOSE," Lvl1Pt Entry(0x%03x) -
> > 0x%016lx\n",
> > > Index1, Lvl1PtEntry[Index1].Uint64));
> > > + }
> > > }
> > > }
> > > }
> > > @@ -510,6 +606,7 @@ PageAttributeToLength (
> > > @param[in] VtdIndex The index used to identify a VTd engine.
> > > @param[in] SecondLevelPagingEntry The second level paging entry in
> > > VTd table for the device.
> > > @param[in] Address The address to be checked.
> > > + @param[in] Is5LevelPaging If it is the 5 level paging.
> > > @param[out] PageAttributes The page attribute of the page entry.
> > >
> > > @return The page entry.
> > > @@ -519,6 +616,7 @@ GetSecondLevelPageTableEntry (
> > > IN UINTN VtdIndex,
> > > IN VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry,
> > > IN PHYSICAL_ADDRESS Address,
> > > + IN BOOLEAN Is5LevelPaging,
> > > OUT PAGE_ATTRIBUTE *PageAttribute
> > > )
> > > {
> > > @@ -526,17 +624,38 @@ GetSecondLevelPageTableEntry (
> > > UINTN Index2;
> > > UINTN Index3;
> > > UINTN Index4;
> > > + UINTN Index5;
> > > UINT64 *L1PageTable;
> > > UINT64 *L2PageTable;
> > > UINT64 *L3PageTable;
> > > UINT64 *L4PageTable;
> > > + UINT64 *L5PageTable;
> > >
> > > + Index5 = ((UINTN)RShiftU64 (Address, 48)) &
> PAGING_VTD_INDEX_MASK;
> > > Index4 = ((UINTN)RShiftU64 (Address, 39)) &
> PAGING_VTD_INDEX_MASK;
> > > Index3 = ((UINTN)Address >> 30) & PAGING_VTD_INDEX_MASK;
> > > Index2 = ((UINTN)Address >> 21) & PAGING_VTD_INDEX_MASK;
> > > Index1 = ((UINTN)Address >> 12) & PAGING_VTD_INDEX_MASK;
> > >
> > > - L4PageTable = (UINT64 *)SecondLevelPagingEntry;
> > > + if (Is5LevelPaging) {
> > > + L5PageTable = (UINT64 *)SecondLevelPagingEntry;
> > > + if (L5PageTable[Index5] == 0) {
> > > + L5PageTable[Index5] = (UINT64)(UINTN)AllocateZeroPages (1);
> > > + if (L5PageTable[Index5] == 0) {
> > > + DEBUG ((DEBUG_ERROR,"!!!!!! ALLOCATE LVL5 PAGE FAIL
> > > (0x%x)!!!!!!\n", Index4));
> > > + ASSERT(FALSE);
> > > + *PageAttribute = PageNone;
> > > + return NULL;
> > > + }
> > > + FlushPageTableMemory (VtdIndex, (UINTN)L5PageTable[Index5],
> > > SIZE_4KB);
> > > + SetSecondLevelPagingEntryAttribute
> > > ((VTD_SECOND_LEVEL_PAGING_ENTRY *)&L5PageTable[Index5],
> > > EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);
> > > + FlushPageTableMemory (VtdIndex, (UINTN)&L5PageTable[Index5],
> > > sizeof(L5PageTable[Index5]));
> > > + }
> > > + L4PageTable = (UINT64 *)(UINTN)(L5PageTable[Index5] &
> > > PAGING_4K_ADDRESS_MASK_64);
> > > + } else {
> > > + L4PageTable = (UINT64 *)SecondLevelPagingEntry; }
> > > +
> > > if (L4PageTable[Index4] == 0) {
> > > L4PageTable[Index4] = (UINT64)(UINTN)AllocateZeroPages (1);
> > > if (L4PageTable[Index4] == 0) {
> > > @@ -785,7 +904,7 @@ SetSecondLevelPagingAttribute (
> > > }
> > >
> > > while (Length != 0) {
> > > - PageEntry = GetSecondLevelPageTableEntry (VtdIndex,
> > > SecondLevelPagingEntry, BaseAddress, &PageAttribute);
> > > + PageEntry = GetSecondLevelPageTableEntry (VtdIndex,
> > > SecondLevelPagingEntry, BaseAddress,
> > > mVtdUnitInformation[VtdIndex].Is5LevelPaging, &PageAttribute);
> > > if (PageEntry == NULL) {
> > > DEBUG ((DEBUG_ERROR, "PageEntry - NULL\n"));
> > > return RETURN_UNSUPPORTED;
> > > @@ -913,7 +1032,7 @@ SetAccessAttribute (
> > >
> > > if (ExtContextEntry != NULL) {
> > > if (ExtContextEntry->Bits.Present == 0) {
> > > - SecondLevelPagingEntry = CreateSecondLevelPagingEntry (VtdIndex,
> 0);
> > > + SecondLevelPagingEntry = CreateSecondLevelPagingEntry
> > > + (VtdIndex, 0,
> > > mVtdUnitInformation[VtdIndex].Is5LevelPaging);
> > > DEBUG ((DEBUG_VERBOSE,"SecondLevelPagingEntry - 0x%x (S%04x
> > > B%02x D%02x F%02x) New\n", SecondLevelPagingEntry, Segment,
> > > SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.Function));
> > > Pt = (UINT64)RShiftU64 ((UINT64)(UINTN)SecondLevelPagingEntry,
> > > 12);
> > >
> > > @@ -922,7 +1041,7 @@ SetAccessAttribute (
> > > ExtContextEntry->Bits.DomainIdentifier = DomainIdentifier;
> > > ExtContextEntry->Bits.Present = 1;
> > > FlushPageTableMemory (VtdIndex, (UINTN)ExtContextEntry,
> > > sizeof(*ExtContextEntry));
> > > - DumpDmarExtContextEntryTable
> > > (mVtdUnitInformation[VtdIndex].ExtRootEntryTable);
> > > + DumpDmarExtContextEntryTable
> > > (mVtdUnitInformation[VtdIndex].ExtRootEntryTable,
> > > mVtdUnitInformation[VtdIndex].Is5LevelPaging);
> > > mVtdUnitInformation[VtdIndex].HasDirtyContext = TRUE;
> > > } else {
> > > SecondLevelPagingEntry = (VOID
> > > *)(UINTN)VTD_64BITS_ADDRESS(ExtContextEntry-
> > > >Bits.SecondLevelPageTranslationPointerLo, ExtContextEntry-
> > > >Bits.SecondLevelPageTranslationPointerHi);
> > > @@ -930,7 +1049,7 @@ SetAccessAttribute (
> > > }
> > > } else if (ContextEntry != NULL) {
> > > if (ContextEntry->Bits.Present == 0) {
> > > - SecondLevelPagingEntry = CreateSecondLevelPagingEntry (VtdIndex,
> 0);
> > > + SecondLevelPagingEntry = CreateSecondLevelPagingEntry
> > > + (VtdIndex, 0,
> > > mVtdUnitInformation[VtdIndex].Is5LevelPaging);
> > > DEBUG ((DEBUG_VERBOSE,"SecondLevelPagingEntry - 0x%x (S%04x
> > > B%02x D%02x F%02x) New\n", SecondLevelPagingEntry, Segment,
> > > SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.Function));
> > > Pt = (UINT64)RShiftU64 ((UINT64)(UINTN)SecondLevelPagingEntry,
> > > 12);
> > >
> > > @@ -939,7 +1058,7 @@ SetAccessAttribute (
> > > ContextEntry->Bits.DomainIdentifier = DomainIdentifier;
> > > ContextEntry->Bits.Present = 1;
> > > FlushPageTableMemory (VtdIndex, (UINTN)ContextEntry,
> > > sizeof(*ContextEntry));
> > > - DumpDmarContextEntryTable
> > > (mVtdUnitInformation[VtdIndex].RootEntryTable);
> > > + DumpDmarContextEntryTable
> > > (mVtdUnitInformation[VtdIndex].RootEntryTable,
> > > mVtdUnitInformation[VtdIndex].Is5LevelPaging);
> > > mVtdUnitInformation[VtdIndex].HasDirtyContext = TRUE;
> > > } else {
> > > SecondLevelPagingEntry = (VOID
> > > *)(UINTN)VTD_64BITS_ADDRESS(ContextEntry-
> > > >Bits.SecondLevelPageTranslationPointerLo, ContextEntry-
> > > >Bits.SecondLevelPageTranslationPointerHi);
> > > @@ -1000,7 +1119,7 @@ AlwaysEnablePageAttribute (
> > >
> > > if (mVtdUnitInformation[VtdIndex].FixedSecondLevelPagingEntry == 0) {
> > > DEBUG((DEBUG_INFO, "CreateSecondLevelPagingEntry - %d\n",
> > > VtdIndex));
> > > - mVtdUnitInformation[VtdIndex].FixedSecondLevelPagingEntry =
> > > CreateSecondLevelPagingEntry (VtdIndex, EDKII_IOMMU_ACCESS_READ |
> > > EDKII_IOMMU_ACCESS_WRITE);
> > > + mVtdUnitInformation[VtdIndex].FixedSecondLevelPagingEntry =
> > > CreateSecondLevelPagingEntry (VtdIndex, EDKII_IOMMU_ACCESS_READ |
> > > EDKII_IOMMU_ACCESS_WRITE,
> > > mVtdUnitInformation[VtdIndex].Is5LevelPaging);
> > > }
> > >
> > > SecondLevelPagingEntry =
> > > mVtdUnitInformation[VtdIndex].FixedSecondLevelPagingEntry;
> > > diff --git
> > >
> a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTableEx.
> > > c
> > >
> b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTableEx.
> > > c
> > > index 0ed9e3ca..3918eeee 100644
> > > ---
> > >
> a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTableEx.
> > > c
> > > +++
> > >
> b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTableEx.
> > > c
> > > @@ -78,11 +78,32 @@ CreateExtContextEntry (
> > >
> > > DEBUG ((DEBUG_INFO,"DOMAIN: S%04x, B%02x D%02x F%02x\n",
> > > mVtdUnitInformation[VtdIndex].Segment, SourceId.Bits.Bus,
> > > SourceId.Bits.Device, SourceId.Bits.Function));
> > >
> > > - if ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW & BIT2) == 0)
> {
> > > - DEBUG((DEBUG_ERROR, "!!!! 4-level page-table is not supported on
> > > VTD %d !!!!\n", VtdIndex));
> > > + mVtdUnitInformation[VtdIndex].Is5LevelPaging = FALSE;
> > > + if ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW & BIT3) != 0)
> {
> > > + if ((PcdGet8(PcdVTdPolicyPropertyMask) & BIT3) != 0) {
> > > + DEBUG((DEBUG_ERROR, "Force to use 4-level page-table on VTD
> > > + %d\n",
> > > VtdIndex));
> > > + ExtContextEntry->Bits.AddressWidth = 0x2;
> > > + } if ((PcdGet8(PcdVTdPolicyPropertyMask) & BIT4) != 0) {
> > > + DEBUG((DEBUG_ERROR, "Force to use 5-level page-table on VTD
> > > + %d\n",
> > > VtdIndex));
> > > + ExtContextEntry->Bits.AddressWidth = 0x3;
> > > + mVtdUnitInformation[VtdIndex].Is5LevelPaging = TRUE;
> > > + } else {
> > > + if (mAcpiDmarTable->HostAddressWidth > 48) {
> > > + DEBUG((DEBUG_ERROR, "Using 5-level page-table on VTD %d\n",
> > > VtdIndex));
> > > + ExtContextEntry->Bits.AddressWidth = 0x3;
> > > + mVtdUnitInformation[VtdIndex].Is5LevelPaging = TRUE;
> > > + } else {
> > > + DEBUG((DEBUG_ERROR, "Using 4-level page-table on VTD %d\n",
> > > VtdIndex));
> > > + ExtContextEntry->Bits.AddressWidth = 0x2;
> > > + }
> > > + }
> > > + } else if ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW &
> > > + BIT2) !=
> > > 0) {
> > > + DEBUG((DEBUG_ERROR, "Using 4-level page-table on VTD %d\n",
> > > VtdIndex));
> > > + ExtContextEntry->Bits.AddressWidth = 0x2;
> > > + } else {
> > > + DEBUG((DEBUG_ERROR, "!!!! Page-table type is not supported on
> > > VTD %d !!!!\n", VtdIndex));
> > > return EFI_UNSUPPORTED;
> > > }
> > > - ExtContextEntry->Bits.AddressWidth = 0x2;
> > > }
> > >
> > > FlushPageTableMemory (VtdIndex,
> > > (UINTN)mVtdUnitInformation[VtdIndex].ExtRootEntryTable,
> > > EFI_PAGES_TO_SIZE(EntryTablePages));
> > > @@ -93,11 +114,13 @@ CreateExtContextEntry (
> > > /**
> > > Dump DMAR extended context entry table.
> > >
> > > - @param[in] ExtRootEntry DMAR extended root entry.
> > > + @param[in] ExtRootEntry DMAR extended root entry.
> > > + @param[in] Is5LevelPaging If it is the 5 level paging.
> > > **/
> > > VOID
> > > DumpDmarExtContextEntryTable (
> > > - IN VTD_EXT_ROOT_ENTRY *ExtRootEntry
> > > + IN VTD_EXT_ROOT_ENTRY *ExtRootEntry, IN BOOLEAN Is5LevelPaging
> > > )
> > > {
> > > UINTN Index;
> > > @@ -127,7 +150,7 @@ DumpDmarExtContextEntryTable (
> > > if (ExtContextEntry[Index2].Bits.Present == 0) {
> > > continue;
> > > }
> > > - DumpSecondLevelPagingEntry ((VOID
> > >
> *)(UINTN)VTD_64BITS_ADDRESS(ExtContextEntry[Index2].Bits.SecondLevelPa
> > > geTranslationPointerLo,
> > > ExtContextEntry[Index2].Bits.SecondLevelPageTranslationPointerHi));
> > > + DumpSecondLevelPagingEntry ((VOID
> > >
> *)(UINTN)VTD_64BITS_ADDRESS(ExtContextEntry[Index2].Bits.SecondLevelPa
> > > geTranslationPointerLo,
> > > ExtContextEntry[Index2].Bits.SecondLevelPageTranslationPointerHi),
> > > Is5LevelPaging);
> > > }
> > >
> > > if (ExtRootEntry[Index].Bits.UpperPresent == 0) { diff --git
> > > a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/VtdReg.c
> > > b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/VtdReg.c
> > > index 699639ba..686d235f 100644
> > > --- a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/VtdReg.c
> > > +++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/VtdReg.c
> > > @@ -174,8 +174,14 @@ PrepareVtdConfig (
> > > if ((mVtdUnitInformation[Index].CapReg.Bits.SLLPS & BIT0) == 0) {
> > > DEBUG((DEBUG_WARN, "!!!! 2MB super page is not supported on
> VTD
> > > %d !!!!\n", Index));
> > > }
> > > - if ((mVtdUnitInformation[Index].CapReg.Bits.SAGAW & BIT2) == 0) {
> > > - DEBUG((DEBUG_ERROR, "!!!! 4-level page-table is not supported on
> > > VTD %d !!!!\n", Index));
> > > + if ((mVtdUnitInformation[Index].CapReg.Bits.SAGAW & BIT3) != 0) {
> > > + DEBUG((DEBUG_INFO, "Support 5-level page-table on VTD %d\n",
> > > Index));
> > > + }
> > > + if ((mVtdUnitInformation[Index].CapReg.Bits.SAGAW & BIT2) != 0) {
> > > + DEBUG((DEBUG_INFO, "Support 4-level page-table on VTD %d\n",
> > > Index));
> > > + }
> > > + if ((mVtdUnitInformation[Index].CapReg.Bits.SAGAW & (BIT3 |
> > > + BIT2)) == 0)
> > > {
> > > + DEBUG((DEBUG_ERROR, "!!!! Page-table type 0x%X is not supported
> > > + on
> > > VTD %d !!!!\n", Index, mVtdUnitInformation[Index].CapReg.Bits.SAGAW));
> > > return ;
> > > }
> > >
> > > diff --git a/Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dec
> > > b/Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dec
> > > index 284820af..8f1edfe2 100644
> > > --- a/Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dec
> > > +++ b/Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dec
> > > @@ -95,6 +95,9 @@
> > > # BIT0: Enable IOMMU during boot (If DMAR table is installed in
> > > DXE. If VTD_INFO_PPI is installed in PEI.)
> > > # BIT1: Enable IOMMU when transfer control to OS (ExitBootService
> > > in normal boot. EndOfPEI in S3)
> > > # BIT2: Force no IOMMU access attribute request recording before
> > > DMAR table is installed.
> > > + # BIT3: Force to use 4 level paging.
> > > + # BIT4: If iommu support 5 level paging, force to use 5 level paging.
> > > + # (If both BIT3 and BIT4 are set, force to use 4 level paging.)
> > > # @Prompt The policy for VTd driver behavior.
> > >
> > >
> gIntelSiliconPkgTokenSpaceGuid.PcdVTdPolicyPropertyMask|1|UINT8|0x000
> > > 00002
> > >
> > > --
> > > 2.16.2.windows.1
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [edk2-devel] [PATCH v3] IntelSiliconPkg/VTd: Add iommu 5 level paging support
[not found] ` <16487A52A9CBAF90.960@groups.io>
@ 2020-11-18 3:03 ` Yao, Jiewen
2020-11-23 8:10 ` Sheng Wei
0 siblings, 1 reply; 6+ messages in thread
From: Yao, Jiewen @ 2020-11-18 3:03 UTC (permalink / raw)
To: devel@edk2.groups.io, Yao, Jiewen, Sheng, W
Cc: Ni, Ray, Chaganty, Rangasai V, Huang, Jenny
Just checked PISMM CPU driver, which use below code to decide if 5 level paging is needed.
https://github.com/tianocore/edk2/blob/master/UefiCpuPkg/PiSmmCpuDxeSmm/X64/PageTbl.c#L75
Can we use the similar algorithm? It just includes check for :
1) Hardware Capability
2) Hardware Address Range
3) Software Execution Mode
And it can be done automatically.
===================
BOOLEAN
Is5LevelPagingNeeded (
VOID
)
{
CPUID_VIR_PHY_ADDRESS_SIZE_EAX VirPhyAddressSize;
CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS_ECX ExtFeatureEcx;
UINT32 MaxExtendedFunctionId;
AsmCpuid (CPUID_EXTENDED_FUNCTION, &MaxExtendedFunctionId, NULL, NULL, NULL);
if (MaxExtendedFunctionId >= CPUID_VIR_PHY_ADDRESS_SIZE) {
AsmCpuid (CPUID_VIR_PHY_ADDRESS_SIZE, &VirPhyAddressSize.Uint32, NULL, NULL, NULL);
} else {
VirPhyAddressSize.Bits.PhysicalAddressBits = 36;
}
AsmCpuidEx (
CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS,
CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS_SUB_LEAF_INFO,
NULL, NULL, &ExtFeatureEcx.Uint32, NULL
);
DEBUG ((
DEBUG_INFO, "PhysicalAddressBits = %d, 5LPageTable = %d.\n",
VirPhyAddressSize.Bits.PhysicalAddressBits, ExtFeatureEcx.Bits.FiveLevelPage
));
if (VirPhyAddressSize.Bits.PhysicalAddressBits > 4 * 9 + 12) {
ASSERT (ExtFeatureEcx.Bits.FiveLevelPage == 1);
return TRUE;
} else {
return FALSE;
}
}
> -----Original Message-----
> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Yao,
> Jiewen
> Sent: Wednesday, November 18, 2020 10:49 AM
> To: Sheng, W <w.sheng@intel.com>; devel@edk2.groups.io
> Cc: Ni, Ray <ray.ni@intel.com>; Chaganty, Rangasai V
> <rangasai.v.chaganty@intel.com>; Huang, Jenny <jenny.huang@intel.com>
> Subject: Re: [edk2-devel] [PATCH v3] IntelSiliconPkg/VTd: Add iommu 5 level
> paging support
>
> Sorry I did not say clearly.
>
> 1) I mean the (SAGAW & BIT2) check should also happen inside of (SAGAW &
> BIT3), the first if.
>
> Otherwise, the logic is:
>
> If (5 level support) {
> If (need 4 level) {
> Do 4 level
> }
> }
>
> That is odd.
>
> 2) In general, I recommend we have a better way to manage test/debug code
> into production. The PCD should be used when it is absolutely necessary.
> I think the policy should be as simple as possible. Otherwise, the production
> team wont know how to choose.
>
>
> > -----Original Message-----
> > From: Sheng, W <w.sheng@intel.com>
> > Sent: Wednesday, November 18, 2020 10:33 AM
> > To: Yao, Jiewen <jiewen.yao@intel.com>; devel@edk2.groups.io
> > Cc: Ni, Ray <ray.ni@intel.com>; Chaganty, Rangasai V
> > <rangasai.v.chaganty@intel.com>; Huang, Jenny <jenny.huang@intel.com>
> > Subject: RE: [PATCH v3] IntelSiliconPkg/VTd: Add iommu 5 level paging
> > support
> >
> > Hi Jeiwen,
> > For comment 1:
> > The code about (SAGAW & BIT2) is just behand (SAGAW & BIT3)
> >
> > > > + DEBUG((DEBUG_ERROR, "Using 4-level page-table on VTD %d\n",
> > > > VtdIndex));
> > > > + ExtContextEntry->Bits.AddressWidth = 0x2;
> > > > + }
> > > > + }
> > > > + } else if ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW &
> > > > + BIT2) !=
> > > > 0) {
> > > > + DEBUG((DEBUG_ERROR, "Using 4-level page-table on VTD %d\n",
> > > > VtdIndex));
> > > > + ExtContextEntry->Bits.AddressWidth = 0x2;
> > > > + } else {
> > > > + DEBUG((DEBUG_ERROR, "!!!! Page-table type is not supported on
> > > > VTD %d !!!!\n", VtdIndex));
> > > > return EFI_UNSUPPORTED;
> > > > }
> > > > - ExtContextEntry->Bits.AddressWidth = 0x2;
> > > > }
> >
> > For comment 2:
> > > # BIT3: Force to use 4 level paging.
> > > # BIT4: If iommu support 5 level paging, force to use 5 level paging.
> > > # (If both BIT3 and BIT4 are set, force to use 4 level paging.)
> > Mostly, these 2 bits are for debug/test purpose, it could be used to force
> the
> > page table depth.
> > Do you think it is no necessary? Or we could find another solution ?
> >
> > Thank you
> > BR
> > Sheng Wei
> >
> >
> > > -----Original Message-----
> > > From: Yao, Jiewen <jiewen.yao@intel.com>
> > > Sent: 2020年11月18日 9:39
> > > To: Sheng, W <w.sheng@intel.com>; devel@edk2.groups.io
> > > Cc: Ni, Ray <ray.ni@intel.com>; Chaganty, Rangasai V
> > > <rangasai.v.chaganty@intel.com>; Huang, Jenny
> <jenny.huang@intel.com>
> > > Subject: RE: [PATCH v3] IntelSiliconPkg/VTd: Add iommu 5 level paging
> > support
> > >
> > > Hi
> > > I have 2 comments:
> > >
> > > 1) below capability check seems not correct.
> > >
> > > (SAGAW & BIT3) is for 5 level only.
> > > We need check (SAGAW & BIT2) for 4 level. But I do not see the code. Do I
> > miss
> > > something?
> > >
> > > if ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW & BIT3) != 0) {
> > > if ((PcdGet8(PcdVTdPolicyPropertyMask) & BIT3) != 0) {
> > > DEBUG((DEBUG_ERROR, "Force to use 4-level page-table on
> > VTD %d\n",
> > > VtdIndex));
> > > ContextEntry->Bits.AddressWidth = 0x2;
> > > } if ((PcdGet8(PcdVTdPolicyPropertyMask) & BIT4) != 0) {
> > > DEBUG((DEBUG_ERROR, "Force to use 5-level page-table on
> > VTD %d\n",
> > > VtdIndex));
> > > ContextEntry->Bits.AddressWidth = 0x3;
> > > mVtdUnitInformation[VtdIndex].Is5LevelPaging = TRUE;
> > > } else {
> > > if (mAcpiDmarTable->HostAddressWidth > 48) {
> > > DEBUG((DEBUG_ERROR, "Using 5-level page-table on VTD %d\n",
> > > VtdIndex));
> > > ContextEntry->Bits.AddressWidth = 0x3;
> > > mVtdUnitInformation[VtdIndex].Is5LevelPaging = TRUE;
> > > } else {
> > > DEBUG((DEBUG_ERROR, "Using 4-level page-table on VTD %d\n",
> > > VtdIndex));
> > > ContextEntry->Bits.AddressWidth = 0x2;
> > > }
> > > }
> > >
> > > 2) I am wondering, do we really need 2 bit for level selection ?
> > > What if force 4 level, but the platform does not support?
> > > What if force 5 level, but the platform does not support?
> > >
> > > # BIT3: Force to use 4 level paging.
> > > # BIT4: If iommu support 5 level paging, force to use 5 level paging.
> > > # (If both BIT3 and BIT4 are set, force to use 4 level paging.)
> > >
> > >
> >
> gIntelSiliconPkgTokenSpaceGuid.PcdVTdPolicyPropertyMask|1|UINT8|0x000
> > 00
> > > 002
> > >
> > > Can we align the solution in DXE/SMM paging solution?
> > >
> > >
> > >
> > > > -----Original Message-----
> > > > From: Sheng, W <w.sheng@intel.com>
> > > > Sent: Wednesday, November 18, 2020 9:18 AM
> > > > To: devel@edk2.groups.io
> > > > Cc: Ni, Ray <ray.ni@intel.com>; Chaganty, Rangasai V
> > > > <rangasai.v.chaganty@intel.com>; Yao, Jiewen <jiewen.yao@intel.com>;
> > > > Huang, Jenny <jenny.huang@intel.com>
> > > > Subject: [PATCH v3] IntelSiliconPkg/VTd: Add iommu 5 level paging
> > > > support
> > > >
> > > > Support iommu 5 level paging for translation table.
> > > >
> > > > REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3067
> > > >
> > > > 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: Jiewen Yao <jiewen.yao@intel.com>
> > > > Cc: Jenny Huang <jenny.huang@intel.com>
> > > > ---
> > > > .../Feature/VTd/IntelVTdDxe/DmaProtection.c | 4 +-
> > > > .../Feature/VTd/IntelVTdDxe/DmaProtection.h | 19 +-
> > > > .../Feature/VTd/IntelVTdDxe/TranslationTable.c | 287
> > +++++++++++++++--
> > > > ----
> > > > .../Feature/VTd/IntelVTdDxe/TranslationTableEx.c | 35 ++-
> > > > .../Feature/VTd/IntelVTdDxe/VtdReg.c | 10 +-
> > > > Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dec | 3 +
> > > > 6 files changed, 258 insertions(+), 100 deletions(-)
> > > >
> > > > diff --git
> > > >
> a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.
> > > > c
> > > >
> b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.
> > > > c
> > > > index 9b6135ef..628565ee 100644
> > > > ---
> > > >
> a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.
> > > > c
> > > > +++
> > > >
> b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.
> > > > c
> > > > @@ -523,10 +523,10 @@ SetupVtd (
> > > > for (Index = 0; Index < mVtdUnitNumber; Index++) {
> > > > DEBUG ((DEBUG_INFO,"VTD Unit %d (Segment: %04x)\n", Index,
> > > > mVtdUnitInformation[Index].Segment));
> > > > if (mVtdUnitInformation[Index].ExtRootEntryTable != NULL) {
> > > > - DumpDmarExtContextEntryTable
> > > > (mVtdUnitInformation[Index].ExtRootEntryTable);
> > > > + DumpDmarExtContextEntryTable
> > > > (mVtdUnitInformation[Index].ExtRootEntryTable,
> > > > mVtdUnitInformation[Index].Is5LevelPaging);
> > > > }
> > > > if (mVtdUnitInformation[Index].RootEntryTable != NULL) {
> > > > - DumpDmarContextEntryTable
> > > > (mVtdUnitInformation[Index].RootEntryTable);
> > > > + DumpDmarContextEntryTable
> > > > (mVtdUnitInformation[Index].RootEntryTable,
> > > > mVtdUnitInformation[Index].Is5LevelPaging);
> > > > }
> > > > }
> > > >
> > > > diff --git
> > > >
> a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.
> > > > h
> > > >
> b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.
> > > > h
> > > > index a3331db8..f641cea0 100644
> > > > ---
> > > >
> a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.
> > > > h
> > > > +++
> > > >
> b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.
> > > > h
> > > > @@ -77,6 +77,7 @@ typedef struct {
> > > > BOOLEAN HasDirtyContext;
> > > > BOOLEAN HasDirtyPages;
> > > > PCI_DEVICE_INFORMATION PciDeviceInfo;
> > > > + BOOLEAN Is5LevelPaging;
> > > > } VTD_UNIT_INFORMATION;
> > > >
> > > > //
> > > > @@ -375,31 +376,37 @@ ParseDmarAcpiTableRmrr (
> > > > /**
> > > > Dump DMAR context entry table.
> > > >
> > > > - @param[in] RootEntry DMAR root entry.
> > > > + @param[in] RootEntry DMAR root entry.
> > > > + @param[in] Is5LevelPaging If it is the 5 level paging.
> > > > **/
> > > > VOID
> > > > DumpDmarContextEntryTable (
> > > > - IN VTD_ROOT_ENTRY *RootEntry
> > > > + IN VTD_ROOT_ENTRY *RootEntry,
> > > > + IN BOOLEAN Is5LevelPaging
> > > > );
> > > >
> > > > /**
> > > > Dump DMAR extended context entry table.
> > > >
> > > > - @param[in] ExtRootEntry DMAR extended root entry.
> > > > + @param[in] ExtRootEntry DMAR extended root entry.
> > > > + @param[in] Is5LevelPaging If it is the 5 level paging.
> > > > **/
> > > > VOID
> > > > DumpDmarExtContextEntryTable (
> > > > - IN VTD_EXT_ROOT_ENTRY *ExtRootEntry
> > > > + IN VTD_EXT_ROOT_ENTRY *ExtRootEntry, IN BOOLEAN
> Is5LevelPaging
> > > > );
> > > >
> > > > /**
> > > > Dump DMAR second level paging entry.
> > > >
> > > > - @param[in] SecondLevelPagingEntry The second level paging entry.
> > > > + @param[in] SecondLevelPagingEntry The second level paging entry.
> > > > + @param[in] Is5LevelPaging If it is the 5 level paging.
> > > > **/
> > > > VOID
> > > > DumpSecondLevelPagingEntry (
> > > > - IN VOID *SecondLevelPagingEntry
> > > > + IN VOID *SecondLevelPagingEntry,
> > > > + IN BOOLEAN Is5LevelPaging
> > > > );
> > > >
> > > > /**
> > > > diff --git
> > > >
> a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTab
> > > > le.c
> > > >
> b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTab
> > > > le.c
> > > > index 201d663d..cb59860a 100644
> > > > ---
> > > >
> a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTab
> > > > le.c
> > > > +++
> > > >
> b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTab
> > > > le.c @@ -128,11 +128,32 @@ CreateContextEntry (
> > > >
> > > > DEBUG ((DEBUG_INFO,"Source: S%04x B%02x D%02x F%02x\n",
> > > > mVtdUnitInformation[VtdIndex].Segment, SourceId.Bits.Bus,
> > > > SourceId.Bits.Device, SourceId.Bits.Function));
> > > >
> > > > - if ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW & BIT2) == 0)
> > {
> > > > - DEBUG((DEBUG_ERROR, "!!!! 4-level page-table is not supported on
> > > > VTD %d !!!!\n", VtdIndex));
> > > > + mVtdUnitInformation[VtdIndex].Is5LevelPaging = FALSE;
> > > > + if ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW & BIT3) != 0)
> > {
> > > > + if ((PcdGet8(PcdVTdPolicyPropertyMask) & BIT3) != 0) {
> > > > + DEBUG((DEBUG_ERROR, "Force to use 4-level page-table on VTD
> > > > + %d\n",
> > > > VtdIndex));
> > > > + ContextEntry->Bits.AddressWidth = 0x2;
> > > > + } if ((PcdGet8(PcdVTdPolicyPropertyMask) & BIT4) != 0) {
> > > > + DEBUG((DEBUG_ERROR, "Force to use 5-level page-table on VTD
> > > > + %d\n",
> > > > VtdIndex));
> > > > + ContextEntry->Bits.AddressWidth = 0x3;
> > > > + mVtdUnitInformation[VtdIndex].Is5LevelPaging = TRUE;
> > > > + } else {
> > > > + if (mAcpiDmarTable->HostAddressWidth > 48) {
> > > > + DEBUG((DEBUG_ERROR, "Using 5-level page-table on VTD %d\n",
> > > > VtdIndex));
> > > > + ContextEntry->Bits.AddressWidth = 0x3;
> > > > + mVtdUnitInformation[VtdIndex].Is5LevelPaging = TRUE;
> > > > + } else {
> > > > + DEBUG((DEBUG_ERROR, "Using 4-level page-table on VTD %d\n",
> > > > VtdIndex));
> > > > + ContextEntry->Bits.AddressWidth = 0x2;
> > > > + }
> > > > + }
> > > > + } else if ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW &
> > > > + BIT2) !=
> > > > 0) {
> > > > + DEBUG((DEBUG_ERROR, "Using 4-level page-table on VTD %d\n",
> > > > VtdIndex));
> > > > + ContextEntry->Bits.AddressWidth = 0x2;
> > > > + } else {
> > > > + DEBUG((DEBUG_ERROR, "!!!! Page-table type is not supported on
> > > > VTD %d !!!!\n", VtdIndex));
> > > > return EFI_UNSUPPORTED;
> > > > }
> > > > - ContextEntry->Bits.AddressWidth = 0x2;
> > > > }
> > > >
> > > > FlushPageTableMemory (VtdIndex,
> > > > (UINTN)mVtdUnitInformation[VtdIndex].RootEntryTable,
> > > > EFI_PAGES_TO_SIZE(EntryTablePages));
> > > > @@ -148,6 +169,7 @@ CreateContextEntry (
> > > > @param[in] MemoryBase The base of the memory.
> > > > @param[in] MemoryLimit The limit of the memory.
> > > > @param[in] IoMmuAccess The IOMMU access.
> > > > + @param[in] Is5LevelPaging If it is the 5 level paging.
> > > >
> > > > @return The second level paging entry.
> > > > **/
> > > > @@ -157,16 +179,23 @@ CreateSecondLevelPagingEntryTable (
> > > > IN VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry,
> > > > IN UINT64 MemoryBase,
> > > > IN UINT64 MemoryLimit,
> > > > - IN UINT64 IoMmuAccess
> > > > + IN UINT64 IoMmuAccess,
> > > > + IN BOOLEAN Is5LevelPaging
> > > > )
> > > > {
> > > > + UINTN Index5;
> > > > UINTN Index4;
> > > > UINTN Index3;
> > > > UINTN Index2;
> > > > + UINTN Lvl5Start;
> > > > + UINTN Lvl5End;
> > > > + UINTN Lvl4PagesStart;
> > > > + UINTN Lvl4PagesEnd;
> > > > UINTN Lvl4Start;
> > > > UINTN Lvl4End;
> > > > UINTN Lvl3Start;
> > > > UINTN Lvl3End;
> > > > + VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl5PtEntry;
> > > > VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl4PtEntry;
> > > > VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl3PtEntry;
> > > > VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl2PtEntry; @@ -184,7
> +213,7
> > > @@
> > > > CreateSecondLevelPagingEntryTable (
> > > > if (SecondLevelPagingEntry == NULL) {
> > > > SecondLevelPagingEntry = AllocateZeroPages (1);
> > > > if (SecondLevelPagingEntry == NULL) {
> > > > - DEBUG ((DEBUG_ERROR,"Could not Alloc LVL4 PT. \n"));
> > > > + DEBUG ((DEBUG_ERROR,"Could not Alloc LVL4 or LVL5 PT. \n"));
> > > > return NULL;
> > > > }
> > > > FlushPageTableMemory (VtdIndex, (UINTN)SecondLevelPagingEntry,
> > > > EFI_PAGES_TO_SIZE(1)); @@ -197,66 +226,109 @@
> > > > CreateSecondLevelPagingEntryTable (
> > > > return SecondLevelPagingEntry;
> > > > }
> > > >
> > > > - Lvl4Start = RShiftU64 (BaseAddress, 39) & 0x1FF;
> > > > - Lvl4End = RShiftU64 (EndAddress - 1, 39) & 0x1FF;
> > > > + if (Is5LevelPaging) {
> > > > + Lvl5Start = RShiftU64 (BaseAddress, 48) & 0x1FF;
> > > > + Lvl5End = RShiftU64 (EndAddress - 1, 48) & 0x1FF;
> > > > + DEBUG ((DEBUG_INFO," Lvl5Start - 0x%x, Lvl5End - 0x%x\n",
> > > > + Lvl5Start,
> > > > Lvl5End));
> > > >
> > > > - DEBUG ((DEBUG_INFO," Lvl4Start - 0x%x, Lvl4End - 0x%x\n",
> > > > Lvl4Start, Lvl4End));
> > > > + Lvl4Start = RShiftU64 (BaseAddress, 39) & 0x1FF;
> > > > + Lvl4End = RShiftU64 (EndAddress - 1, 39) & 0x1FF;
> > > >
> > > > - Lvl4PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> > > > *)SecondLevelPagingEntry;
> > > > - for (Index4 = Lvl4Start; Index4 <= Lvl4End; Index4++) {
> > > > - if (Lvl4PtEntry[Index4].Uint64 == 0) {
> > > > - Lvl4PtEntry[Index4].Uint64 = (UINT64)(UINTN)AllocateZeroPages (1);
> > > > - if (Lvl4PtEntry[Index4].Uint64 == 0) {
> > > > - DEBUG ((DEBUG_ERROR,"!!!!!! ALLOCATE LVL4 PAGE FAIL
> > > > (0x%x)!!!!!!\n", Index4));
> > > > - ASSERT(FALSE);
> > > > - return NULL;
> > > > - }
> > > > - FlushPageTableMemory (VtdIndex,
> > (UINTN)Lvl4PtEntry[Index4].Uint64,
> > > > SIZE_4KB);
> > > > - SetSecondLevelPagingEntryAttribute (&Lvl4PtEntry[Index4],
> > > > EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);
> > > > - }
> > > > + Lvl4PagesStart = (Lvl5Start<<9) | Lvl4Start;
> > > > + Lvl4PagesEnd = (Lvl5End<<9) | Lvl4End;
> > > > + DEBUG ((DEBUG_INFO," Lvl4PagesStart - 0x%x, Lvl4PagesEnd -
> > > > + 0x%x\n",
> > > > Lvl4PagesStart, Lvl4PagesEnd));
> > > >
> > > > - Lvl3Start = RShiftU64 (BaseAddress, 30) & 0x1FF;
> > > > - if (ALIGN_VALUE_LOW(BaseAddress + SIZE_1GB, SIZE_1GB) <=
> > > > EndAddress) {
> > > > - Lvl3End = SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY) - 1;
> > > > - } else {
> > > > - Lvl3End = RShiftU64 (EndAddress - 1, 30) & 0x1FF;
> > > > + Lvl5PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> > > > *)SecondLevelPagingEntry;
> > > > + } else {
> > > > + Lvl5Start = RShiftU64 (BaseAddress, 48) & 0x1FF;
> > > > + Lvl5End = Lvl5Start;
> > > > +
> > > > + Lvl4Start = RShiftU64 (BaseAddress, 39) & 0x1FF;
> > > > + Lvl4End = RShiftU64 (EndAddress - 1, 39) & 0x1FF;
> > > > + DEBUG ((DEBUG_INFO," Lvl4Start - 0x%x, Lvl4End - 0x%x\n",
> > > > + Lvl4Start,
> > > > Lvl4End));
> > > > +
> > > > + Lvl4PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> > > > *)SecondLevelPagingEntry;
> > > > + }
> > > > +
> > > > + for (Index5 = Lvl5Start; Index5 <= Lvl5End; Index5++) {
> > > > + if (Is5LevelPaging) {
> > > > + if (Lvl5PtEntry[Index5].Uint64 == 0) {
> > > > + Lvl5PtEntry[Index5].Uint64 = (UINT64)(UINTN)AllocateZeroPages
> (1);
> > > > + if (Lvl5PtEntry[Index5].Uint64 == 0) {
> > > > + DEBUG ((DEBUG_ERROR,"!!!!!! ALLOCATE LVL4 PAGE FAIL
> > > > (0x%x)!!!!!!\n", Index5));
> > > > + ASSERT(FALSE);
> > > > + return NULL;
> > > > + }
> > > > + FlushPageTableMemory (VtdIndex,
> > > > + (UINTN)Lvl5PtEntry[Index5].Uint64,
> > > > SIZE_4KB);
> > > > + SetSecondLevelPagingEntryAttribute (&Lvl5PtEntry[Index5],
> > > > EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);
> > > > + }
> > > > + Lvl4Start = Lvl4PagesStart & 0x1FF;
> > > > + if (((Index5+1)<<9) > Lvl4PagesEnd) {
> > > > + Lvl4End = SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY) -
> > 1;;
> > > > + Lvl4PagesStart = (Index5+1)<<9;
> > > > + } else {
> > > > + Lvl4End = Lvl4PagesEnd & 0x1FF;
> > > > + }
> > > > + DEBUG ((DEBUG_INFO," Lvl5(0x%x): Lvl4Start - 0x%x, Lvl4End -
> > > > + 0x%x\n",
> > > > Index5, Lvl4Start, Lvl4End));
> > > > + Lvl4PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> > > > *)(UINTN)VTD_64BITS_ADDRESS(Lvl5PtEntry[Index5].Bits.AddressLo,
> > > > Lvl5PtEntry[Index5].Bits.AddressHi);
> > > > }
> > > > - DEBUG ((DEBUG_INFO," Lvl4(0x%x): Lvl3Start - 0x%x, Lvl3End -
> > 0x%x\n",
> > > > Index4, Lvl3Start, Lvl3End));
> > > >
> > > > - Lvl3PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> > > > *)(UINTN)VTD_64BITS_ADDRESS(Lvl4PtEntry[Index4].Bits.AddressLo,
> > > > Lvl4PtEntry[Index4].Bits.AddressHi);
> > > > - for (Index3 = Lvl3Start; Index3 <= Lvl3End; Index3++) {
> > > > - if (Lvl3PtEntry[Index3].Uint64 == 0) {
> > > > - Lvl3PtEntry[Index3].Uint64 = (UINT64)(UINTN)AllocateZeroPages
> (1);
> > > > - if (Lvl3PtEntry[Index3].Uint64 == 0) {
> > > > - DEBUG ((DEBUG_ERROR,"!!!!!! ALLOCATE LVL3 PAGE FAIL (0x%x,
> > > > 0x%x)!!!!!!\n", Index4, Index3));
> > > > + for (Index4 = Lvl4Start; Index4 <= Lvl4End; Index4++) {
> > > > + if (Lvl4PtEntry[Index4].Uint64 == 0) {
> > > > + Lvl4PtEntry[Index4].Uint64 = (UINT64)(UINTN)AllocateZeroPages
> (1);
> > > > + if (Lvl4PtEntry[Index4].Uint64 == 0) {
> > > > + DEBUG ((DEBUG_ERROR,"!!!!!! ALLOCATE LVL4 PAGE FAIL
> > > > (0x%x)!!!!!!\n", Index4));
> > > > ASSERT(FALSE);
> > > > return NULL;
> > > > }
> > > > - FlushPageTableMemory (VtdIndex,
> > (UINTN)Lvl3PtEntry[Index3].Uint64,
> > > > SIZE_4KB);
> > > > - SetSecondLevelPagingEntryAttribute (&Lvl3PtEntry[Index3],
> > > > EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);
> > > > + FlushPageTableMemory (VtdIndex,
> > > > + (UINTN)Lvl4PtEntry[Index4].Uint64,
> > > > SIZE_4KB);
> > > > + SetSecondLevelPagingEntryAttribute (&Lvl4PtEntry[Index4],
> > > > EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);
> > > > }
> > > >
> > > > - Lvl2PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> > > > *)(UINTN)VTD_64BITS_ADDRESS(Lvl3PtEntry[Index3].Bits.AddressLo,
> > > > Lvl3PtEntry[Index3].Bits.AddressHi);
> > > > - for (Index2 = 0; Index2 <
> > > > SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY); Index2++) {
> > > > - Lvl2PtEntry[Index2].Uint64 = BaseAddress;
> > > > - SetSecondLevelPagingEntryAttribute (&Lvl2PtEntry[Index2],
> > > > IoMmuAccess);
> > > > - Lvl2PtEntry[Index2].Bits.PageSize = 1;
> > > > - BaseAddress += SIZE_2MB;
> > > > + Lvl3Start = RShiftU64 (BaseAddress, 30) & 0x1FF;
> > > > + if (ALIGN_VALUE_LOW(BaseAddress + SIZE_1GB, SIZE_1GB) <=
> > > > EndAddress) {
> > > > + Lvl3End = SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY) -
> 1;
> > > > + } else {
> > > > + Lvl3End = RShiftU64 (EndAddress - 1, 30) & 0x1FF;
> > > > + }
> > > > + DEBUG ((DEBUG_INFO," Lvl4(0x%x): Lvl3Start - 0x%x, Lvl3End -
> > > > + 0x%x\n",
> > > > Index4, Lvl3Start, Lvl3End));
> > > > +
> > > > + Lvl3PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> > > > *)(UINTN)VTD_64BITS_ADDRESS(Lvl4PtEntry[Index4].Bits.AddressLo,
> > > > Lvl4PtEntry[Index4].Bits.AddressHi);
> > > > + for (Index3 = Lvl3Start; Index3 <= Lvl3End; Index3++) {
> > > > + if (Lvl3PtEntry[Index3].Uint64 == 0) {
> > > > + Lvl3PtEntry[Index3].Uint64 = (UINT64)(UINTN)AllocateZeroPages
> > (1);
> > > > + if (Lvl3PtEntry[Index3].Uint64 == 0) {
> > > > + DEBUG ((DEBUG_ERROR,"!!!!!! ALLOCATE LVL3 PAGE FAIL
> > > > + (0x%x,
> > > > 0x%x)!!!!!!\n", Index4, Index3));
> > > > + ASSERT(FALSE);
> > > > + return NULL;
> > > > + }
> > > > + FlushPageTableMemory (VtdIndex,
> > > > + (UINTN)Lvl3PtEntry[Index3].Uint64,
> > > > SIZE_4KB);
> > > > + SetSecondLevelPagingEntryAttribute (&Lvl3PtEntry[Index3],
> > > > EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);
> > > > + }
> > > > +
> > > > + Lvl2PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> > > > *)(UINTN)VTD_64BITS_ADDRESS(Lvl3PtEntry[Index3].Bits.AddressLo,
> > > > Lvl3PtEntry[Index3].Bits.AddressHi);
> > > > + for (Index2 = 0; Index2 <
> > > > SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY); Index2++) {
> > > > + Lvl2PtEntry[Index2].Uint64 = BaseAddress;
> > > > + SetSecondLevelPagingEntryAttribute (&Lvl2PtEntry[Index2],
> > > > IoMmuAccess);
> > > > + Lvl2PtEntry[Index2].Bits.PageSize = 1;
> > > > + BaseAddress += SIZE_2MB;
> > > > + if (BaseAddress >= MemoryLimit) {
> > > > + break;
> > > > + }
> > > > + }
> > > > + FlushPageTableMemory (VtdIndex, (UINTN)Lvl2PtEntry,
> > > > + SIZE_4KB);
> > > > if (BaseAddress >= MemoryLimit) {
> > > > break;
> > > > }
> > > > }
> > > > - FlushPageTableMemory (VtdIndex, (UINTN)Lvl2PtEntry, SIZE_4KB);
> > > > + FlushPageTableMemory (VtdIndex, (UINTN)&Lvl3PtEntry[Lvl3Start],
> > > > (UINTN)&Lvl3PtEntry[Lvl3End + 1] - (UINTN)&Lvl3PtEntry[Lvl3Start]);
> > > > if (BaseAddress >= MemoryLimit) {
> > > > break;
> > > > }
> > > > }
> > > > - FlushPageTableMemory (VtdIndex, (UINTN)&Lvl3PtEntry[Lvl3Start],
> > > > (UINTN)&Lvl3PtEntry[Lvl3End + 1] - (UINTN)&Lvl3PtEntry[Lvl3Start]);
> > > > - if (BaseAddress >= MemoryLimit) {
> > > > - break;
> > > > - }
> > > > + FlushPageTableMemory (VtdIndex, (UINTN)&Lvl4PtEntry[Lvl4Start],
> > > > (UINTN)&Lvl4PtEntry[Lvl4End + 1] - (UINTN)&Lvl4PtEntry[Lvl4Start]);
> > > > }
> > > > - FlushPageTableMemory (VtdIndex, (UINTN)&Lvl4PtEntry[Lvl4Start],
> > > > (UINTN)&Lvl4PtEntry[Lvl4End + 1] - (UINTN)&Lvl4PtEntry[Lvl4Start]);
> > > > + FlushPageTableMemory (VtdIndex, (UINTN)&Lvl5PtEntry[Lvl5Start],
> > > > (UINTN)&Lvl5PtEntry[Lvl5End + 1] - (UINTN)&Lvl5PtEntry[Lvl5Start]);
> > > >
> > > > return SecondLevelPagingEntry;
> > > > }
> > > > @@ -266,26 +338,28 @@ CreateSecondLevelPagingEntryTable (
> > > >
> > > > @param[in] VtdIndex The index of the VTd engine.
> > > > @param[in] IoMmuAccess The IOMMU access.
> > > > + @param[in] Is5LevelPaging If it is the 5 level paging.
> > > >
> > > > @return The second level paging entry.
> > > > **/
> > > > VTD_SECOND_LEVEL_PAGING_ENTRY *
> > > > CreateSecondLevelPagingEntry (
> > > > IN UINTN VtdIndex,
> > > > - IN UINT64 IoMmuAccess
> > > > + IN UINT64 IoMmuAccess,
> > > > + IN BOOLEAN Is5LevelPaging
> > > > )
> > > > {
> > > > VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry;
> > > >
> > > > SecondLevelPagingEntry = NULL;
> > > > - SecondLevelPagingEntry = CreateSecondLevelPagingEntryTable
> > > > (VtdIndex, SecondLevelPagingEntry, 0, mBelow4GMemoryLimit,
> > > > IoMmuAccess);
> > > > + SecondLevelPagingEntry = CreateSecondLevelPagingEntryTable
> > > > + (VtdIndex,
> > > > SecondLevelPagingEntry, 0, mBelow4GMemoryLimit, IoMmuAccess,
> > > > Is5LevelPaging);
> > > > if (SecondLevelPagingEntry == NULL) {
> > > > return NULL;
> > > > }
> > > >
> > > > if (mAbove4GMemoryLimit != 0) {
> > > > ASSERT (mAbove4GMemoryLimit > BASE_4GB);
> > > > - SecondLevelPagingEntry = CreateSecondLevelPagingEntryTable
> > (VtdIndex,
> > > > SecondLevelPagingEntry, SIZE_4GB, mAbove4GMemoryLimit,
> > IoMmuAccess);
> > > > + SecondLevelPagingEntry = CreateSecondLevelPagingEntryTable
> > > > + (VtdIndex,
> > > > SecondLevelPagingEntry, SIZE_4GB, mAbove4GMemoryLimit,
> > IoMmuAccess,
> > > > Is5LevelPaging);
> > > > if (SecondLevelPagingEntry == NULL) {
> > > > return NULL;
> > > > }
> > > > @@ -326,11 +400,13 @@ SetupTranslationTable (
> > > > /**
> > > > Dump DMAR context entry table.
> > > >
> > > > - @param[in] RootEntry DMAR root entry.
> > > > + @param[in] RootEntry DMAR root entry.
> > > > + @param[in] Is5LevelPaging If it is the 5 level paging.
> > > > **/
> > > > VOID
> > > > DumpDmarContextEntryTable (
> > > > - IN VTD_ROOT_ENTRY *RootEntry
> > > > + IN VTD_ROOT_ENTRY *RootEntry,
> > > > + IN BOOLEAN Is5LevelPaging
> > > > )
> > > > {
> > > > UINTN Index;
> > > > @@ -359,7 +435,7 @@ DumpDmarContextEntryTable (
> > > > if (ContextEntry[Index2].Bits.Present == 0) {
> > > > continue;
> > > > }
> > > > - DumpSecondLevelPagingEntry ((VOID
> > > >
> >
> *)(UINTN)VTD_64BITS_ADDRESS(ContextEntry[Index2].Bits.SecondLevelPage
> > > > TranslationPointerLo,
> > > > ContextEntry[Index2].Bits.SecondLevelPageTranslationPointerHi));
> > > > + DumpSecondLevelPagingEntry ((VOID
> > > >
> >
> *)(UINTN)VTD_64BITS_ADDRESS(ContextEntry[Index2].Bits.SecondLevelPage
> > > > TranslationPointerLo,
> > > > ContextEntry[Index2].Bits.SecondLevelPageTranslationPointerHi),
> > > > Is5LevelPaging);
> > > > }
> > > > }
> > > > DEBUG ((DEBUG_INFO,"=========================\n"));
> > > > @@ -368,17 +444,22 @@ DumpDmarContextEntryTable (
> > > > /**
> > > > Dump DMAR second level paging entry.
> > > >
> > > > - @param[in] SecondLevelPagingEntry The second level paging entry.
> > > > + @param[in] SecondLevelPagingEntry The second level paging entry.
> > > > + @param[in] Is5LevelPaging If it is the 5 level paging.
> > > > **/
> > > > VOID
> > > > DumpSecondLevelPagingEntry (
> > > > - IN VOID *SecondLevelPagingEntry
> > > > + IN VOID *SecondLevelPagingEntry,
> > > > + IN BOOLEAN Is5LevelPaging
> > > > )
> > > > {
> > > > + UINTN Index5;
> > > > UINTN Index4;
> > > > UINTN Index3;
> > > > UINTN Index2;
> > > > UINTN Index1;
> > > > + UINTN Lvl5IndexEnd;
> > > > + VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl5PtEntry;
> > > > VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl4PtEntry;
> > > > VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl3PtEntry;
> > > > VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl2PtEntry; @@ -386,38
> > +467,53
> > > @@
> > > > DumpSecondLevelPagingEntry (
> > > >
> > > > DEBUG ((DEBUG_VERBOSE,"================\n"));
> > > > DEBUG ((DEBUG_VERBOSE,"DMAR Second Level Page Table:\n"));
> > > > + DEBUG ((DEBUG_VERBOSE,"SecondLevelPagingEntry Base - 0x%x,
> > > > Is5LevelPaging - %d\n", SecondLevelPagingEntry, Is5LevelPaging));
> > > >
> > > > - DEBUG ((DEBUG_VERBOSE,"SecondLevelPagingEntry Base - 0x%x\n",
> > > > SecondLevelPagingEntry));
> > > > + Lvl5IndexEnd = Is5LevelPaging ?
> > > > SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY) : 1;
> > > > Lvl4PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> > > > *)SecondLevelPagingEntry;
> > > > - for (Index4 = 0; Index4 <
> > > > SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY); Index4++) {
> > > > - if (Lvl4PtEntry[Index4].Uint64 != 0) {
> > > > - DEBUG ((DEBUG_VERBOSE," Lvl4Pt Entry(0x%03x) - 0x%016lx\n",
> > Index4,
> > > > Lvl4PtEntry[Index4].Uint64));
> > > > - }
> > > > - if (Lvl4PtEntry[Index4].Uint64 == 0) {
> > > > - continue;
> > > > - }
> > > > - Lvl3PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> > > > *)(UINTN)VTD_64BITS_ADDRESS(Lvl4PtEntry[Index4].Bits.AddressLo,
> > > > Lvl4PtEntry[Index4].Bits.AddressHi);
> > > > - for (Index3 = 0; Index3 <
> > > > SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY); Index3++) {
> > > > - if (Lvl3PtEntry[Index3].Uint64 != 0) {
> > > > - DEBUG ((DEBUG_VERBOSE," Lvl3Pt Entry(0x%03x) - 0x%016lx\n",
> > > > Index3, Lvl3PtEntry[Index3].Uint64));
> > > > + Lvl5PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> > > > *)SecondLevelPagingEntry;
> > > > +
> > > > + for (Index5 = 0; Index5 < Lvl5IndexEnd; Index5++) {
> > > > + if (Is5LevelPaging) {
> > > > + if (Lvl5PtEntry[Index5].Uint64 != 0) {
> > > > + DEBUG ((DEBUG_VERBOSE," Lvl5Pt Entry(0x%03x) - 0x%016lx\n",
> > > > Index5, Lvl5PtEntry[Index5].Uint64));
> > > > }
> > > > - if (Lvl3PtEntry[Index3].Uint64 == 0) {
> > > > + if (Lvl5PtEntry[Index5].Uint64 == 0) {
> > > > continue;
> > > > }
> > > > + Lvl4PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> > > > *)(UINTN)VTD_64BITS_ADDRESS(Lvl5PtEntry[Index5].Bits.AddressLo,
> > > > Lvl5PtEntry[Index5].Bits.AddressHi);
> > > > + }
> > > >
> > > > - Lvl2PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> > > > *)(UINTN)VTD_64BITS_ADDRESS(Lvl3PtEntry[Index3].Bits.AddressLo,
> > > > Lvl3PtEntry[Index3].Bits.AddressHi);
> > > > - for (Index2 = 0; Index2 <
> > > > SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY); Index2++) {
> > > > - if (Lvl2PtEntry[Index2].Uint64 != 0) {
> > > > - DEBUG ((DEBUG_VERBOSE," Lvl2Pt Entry(0x%03x) -
> 0x%016lx\n",
> > > > Index2, Lvl2PtEntry[Index2].Uint64));
> > > > + for (Index4 = 0; Index4 <
> > > > SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY); Index4++) {
> > > > + if (Lvl4PtEntry[Index4].Uint64 != 0) {
> > > > + DEBUG ((DEBUG_VERBOSE," Lvl4Pt Entry(0x%03x) - 0x%016lx\n",
> > > > Index4, Lvl4PtEntry[Index4].Uint64));
> > > > + }
> > > > + if (Lvl4PtEntry[Index4].Uint64 == 0) {
> > > > + continue;
> > > > + }
> > > > + Lvl3PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> > > > *)(UINTN)VTD_64BITS_ADDRESS(Lvl4PtEntry[Index4].Bits.AddressLo,
> > > > Lvl4PtEntry[Index4].Bits.AddressHi);
> > > > + for (Index3 = 0; Index3 <
> > > > SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY); Index3++) {
> > > > + if (Lvl3PtEntry[Index3].Uint64 != 0) {
> > > > + DEBUG ((DEBUG_VERBOSE," Lvl3Pt Entry(0x%03x) - 0x%016lx\n",
> > > > Index3, Lvl3PtEntry[Index3].Uint64));
> > > > }
> > > > - if (Lvl2PtEntry[Index2].Uint64 == 0) {
> > > > + if (Lvl3PtEntry[Index3].Uint64 == 0) {
> > > > continue;
> > > > }
> > > > - if (Lvl2PtEntry[Index2].Bits.PageSize == 0) {
> > > > - Lvl1PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> > > > *)(UINTN)VTD_64BITS_ADDRESS(Lvl2PtEntry[Index2].Bits.AddressLo,
> > > > Lvl2PtEntry[Index2].Bits.AddressHi);
> > > > - for (Index1 = 0; Index1 <
> > > > SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY); Index1++) {
> > > > - if (Lvl1PtEntry[Index1].Uint64 != 0) {
> > > > - DEBUG ((DEBUG_VERBOSE," Lvl1Pt Entry(0x%03x) -
> > > 0x%016lx\n",
> > > > Index1, Lvl1PtEntry[Index1].Uint64));
> > > > +
> > > > + Lvl2PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> > > > *)(UINTN)VTD_64BITS_ADDRESS(Lvl3PtEntry[Index3].Bits.AddressLo,
> > > > Lvl3PtEntry[Index3].Bits.AddressHi);
> > > > + for (Index2 = 0; Index2 <
> > > > SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY); Index2++) {
> > > > + if (Lvl2PtEntry[Index2].Uint64 != 0) {
> > > > + DEBUG ((DEBUG_VERBOSE," Lvl2Pt Entry(0x%03x) -
> 0x%016lx\n",
> > > > Index2, Lvl2PtEntry[Index2].Uint64));
> > > > + }
> > > > + if (Lvl2PtEntry[Index2].Uint64 == 0) {
> > > > + continue;
> > > > + }
> > > > + if (Lvl2PtEntry[Index2].Bits.PageSize == 0) {
> > > > + Lvl1PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> > > > *)(UINTN)VTD_64BITS_ADDRESS(Lvl2PtEntry[Index2].Bits.AddressLo,
> > > > Lvl2PtEntry[Index2].Bits.AddressHi);
> > > > + for (Index1 = 0; Index1 <
> > > > SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY); Index1++) {
> > > > + if (Lvl1PtEntry[Index1].Uint64 != 0) {
> > > > + DEBUG ((DEBUG_VERBOSE," Lvl1Pt Entry(0x%03x) -
> > > 0x%016lx\n",
> > > > Index1, Lvl1PtEntry[Index1].Uint64));
> > > > + }
> > > > }
> > > > }
> > > > }
> > > > @@ -510,6 +606,7 @@ PageAttributeToLength (
> > > > @param[in] VtdIndex The index used to identify a VTd
> engine.
> > > > @param[in] SecondLevelPagingEntry The second level paging entry
> in
> > > > VTd table for the device.
> > > > @param[in] Address The address to be checked.
> > > > + @param[in] Is5LevelPaging If it is the 5 level paging.
> > > > @param[out] PageAttributes The page attribute of the page
> entry.
> > > >
> > > > @return The page entry.
> > > > @@ -519,6 +616,7 @@ GetSecondLevelPageTableEntry (
> > > > IN UINTN VtdIndex,
> > > > IN VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry,
> > > > IN PHYSICAL_ADDRESS Address,
> > > > + IN BOOLEAN Is5LevelPaging,
> > > > OUT PAGE_ATTRIBUTE *PageAttribute
> > > > )
> > > > {
> > > > @@ -526,17 +624,38 @@ GetSecondLevelPageTableEntry (
> > > > UINTN Index2;
> > > > UINTN Index3;
> > > > UINTN Index4;
> > > > + UINTN Index5;
> > > > UINT64 *L1PageTable;
> > > > UINT64 *L2PageTable;
> > > > UINT64 *L3PageTable;
> > > > UINT64 *L4PageTable;
> > > > + UINT64 *L5PageTable;
> > > >
> > > > + Index5 = ((UINTN)RShiftU64 (Address, 48)) &
> > PAGING_VTD_INDEX_MASK;
> > > > Index4 = ((UINTN)RShiftU64 (Address, 39)) &
> > PAGING_VTD_INDEX_MASK;
> > > > Index3 = ((UINTN)Address >> 30) & PAGING_VTD_INDEX_MASK;
> > > > Index2 = ((UINTN)Address >> 21) & PAGING_VTD_INDEX_MASK;
> > > > Index1 = ((UINTN)Address >> 12) & PAGING_VTD_INDEX_MASK;
> > > >
> > > > - L4PageTable = (UINT64 *)SecondLevelPagingEntry;
> > > > + if (Is5LevelPaging) {
> > > > + L5PageTable = (UINT64 *)SecondLevelPagingEntry;
> > > > + if (L5PageTable[Index5] == 0) {
> > > > + L5PageTable[Index5] = (UINT64)(UINTN)AllocateZeroPages (1);
> > > > + if (L5PageTable[Index5] == 0) {
> > > > + DEBUG ((DEBUG_ERROR,"!!!!!! ALLOCATE LVL5 PAGE FAIL
> > > > (0x%x)!!!!!!\n", Index4));
> > > > + ASSERT(FALSE);
> > > > + *PageAttribute = PageNone;
> > > > + return NULL;
> > > > + }
> > > > + FlushPageTableMemory (VtdIndex, (UINTN)L5PageTable[Index5],
> > > > SIZE_4KB);
> > > > + SetSecondLevelPagingEntryAttribute
> > > > ((VTD_SECOND_LEVEL_PAGING_ENTRY *)&L5PageTable[Index5],
> > > > EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);
> > > > + FlushPageTableMemory (VtdIndex, (UINTN)&L5PageTable[Index5],
> > > > sizeof(L5PageTable[Index5]));
> > > > + }
> > > > + L4PageTable = (UINT64 *)(UINTN)(L5PageTable[Index5] &
> > > > PAGING_4K_ADDRESS_MASK_64);
> > > > + } else {
> > > > + L4PageTable = (UINT64 *)SecondLevelPagingEntry; }
> > > > +
> > > > if (L4PageTable[Index4] == 0) {
> > > > L4PageTable[Index4] = (UINT64)(UINTN)AllocateZeroPages (1);
> > > > if (L4PageTable[Index4] == 0) {
> > > > @@ -785,7 +904,7 @@ SetSecondLevelPagingAttribute (
> > > > }
> > > >
> > > > while (Length != 0) {
> > > > - PageEntry = GetSecondLevelPageTableEntry (VtdIndex,
> > > > SecondLevelPagingEntry, BaseAddress, &PageAttribute);
> > > > + PageEntry = GetSecondLevelPageTableEntry (VtdIndex,
> > > > SecondLevelPagingEntry, BaseAddress,
> > > > mVtdUnitInformation[VtdIndex].Is5LevelPaging, &PageAttribute);
> > > > if (PageEntry == NULL) {
> > > > DEBUG ((DEBUG_ERROR, "PageEntry - NULL\n"));
> > > > return RETURN_UNSUPPORTED;
> > > > @@ -913,7 +1032,7 @@ SetAccessAttribute (
> > > >
> > > > if (ExtContextEntry != NULL) {
> > > > if (ExtContextEntry->Bits.Present == 0) {
> > > > - SecondLevelPagingEntry = CreateSecondLevelPagingEntry (VtdIndex,
> > 0);
> > > > + SecondLevelPagingEntry = CreateSecondLevelPagingEntry
> > > > + (VtdIndex, 0,
> > > > mVtdUnitInformation[VtdIndex].Is5LevelPaging);
> > > > DEBUG ((DEBUG_VERBOSE,"SecondLevelPagingEntry - 0x%x (S%04x
> > > > B%02x D%02x F%02x) New\n", SecondLevelPagingEntry, Segment,
> > > > SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.Function));
> > > > Pt = (UINT64)RShiftU64 ((UINT64)(UINTN)SecondLevelPagingEntry,
> > > > 12);
> > > >
> > > > @@ -922,7 +1041,7 @@ SetAccessAttribute (
> > > > ExtContextEntry->Bits.DomainIdentifier = DomainIdentifier;
> > > > ExtContextEntry->Bits.Present = 1;
> > > > FlushPageTableMemory (VtdIndex, (UINTN)ExtContextEntry,
> > > > sizeof(*ExtContextEntry));
> > > > - DumpDmarExtContextEntryTable
> > > > (mVtdUnitInformation[VtdIndex].ExtRootEntryTable);
> > > > + DumpDmarExtContextEntryTable
> > > > (mVtdUnitInformation[VtdIndex].ExtRootEntryTable,
> > > > mVtdUnitInformation[VtdIndex].Is5LevelPaging);
> > > > mVtdUnitInformation[VtdIndex].HasDirtyContext = TRUE;
> > > > } else {
> > > > SecondLevelPagingEntry = (VOID
> > > > *)(UINTN)VTD_64BITS_ADDRESS(ExtContextEntry-
> > > > >Bits.SecondLevelPageTranslationPointerLo, ExtContextEntry-
> > > > >Bits.SecondLevelPageTranslationPointerHi);
> > > > @@ -930,7 +1049,7 @@ SetAccessAttribute (
> > > > }
> > > > } else if (ContextEntry != NULL) {
> > > > if (ContextEntry->Bits.Present == 0) {
> > > > - SecondLevelPagingEntry = CreateSecondLevelPagingEntry (VtdIndex,
> > 0);
> > > > + SecondLevelPagingEntry = CreateSecondLevelPagingEntry
> > > > + (VtdIndex, 0,
> > > > mVtdUnitInformation[VtdIndex].Is5LevelPaging);
> > > > DEBUG ((DEBUG_VERBOSE,"SecondLevelPagingEntry - 0x%x (S%04x
> > > > B%02x D%02x F%02x) New\n", SecondLevelPagingEntry, Segment,
> > > > SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.Function));
> > > > Pt = (UINT64)RShiftU64 ((UINT64)(UINTN)SecondLevelPagingEntry,
> > > > 12);
> > > >
> > > > @@ -939,7 +1058,7 @@ SetAccessAttribute (
> > > > ContextEntry->Bits.DomainIdentifier = DomainIdentifier;
> > > > ContextEntry->Bits.Present = 1;
> > > > FlushPageTableMemory (VtdIndex, (UINTN)ContextEntry,
> > > > sizeof(*ContextEntry));
> > > > - DumpDmarContextEntryTable
> > > > (mVtdUnitInformation[VtdIndex].RootEntryTable);
> > > > + DumpDmarContextEntryTable
> > > > (mVtdUnitInformation[VtdIndex].RootEntryTable,
> > > > mVtdUnitInformation[VtdIndex].Is5LevelPaging);
> > > > mVtdUnitInformation[VtdIndex].HasDirtyContext = TRUE;
> > > > } else {
> > > > SecondLevelPagingEntry = (VOID
> > > > *)(UINTN)VTD_64BITS_ADDRESS(ContextEntry-
> > > > >Bits.SecondLevelPageTranslationPointerLo, ContextEntry-
> > > > >Bits.SecondLevelPageTranslationPointerHi);
> > > > @@ -1000,7 +1119,7 @@ AlwaysEnablePageAttribute (
> > > >
> > > > if (mVtdUnitInformation[VtdIndex].FixedSecondLevelPagingEntry == 0)
> {
> > > > DEBUG((DEBUG_INFO, "CreateSecondLevelPagingEntry - %d\n",
> > > > VtdIndex));
> > > > - mVtdUnitInformation[VtdIndex].FixedSecondLevelPagingEntry =
> > > > CreateSecondLevelPagingEntry (VtdIndex, EDKII_IOMMU_ACCESS_READ
> |
> > > > EDKII_IOMMU_ACCESS_WRITE);
> > > > + mVtdUnitInformation[VtdIndex].FixedSecondLevelPagingEntry =
> > > > CreateSecondLevelPagingEntry (VtdIndex, EDKII_IOMMU_ACCESS_READ
> |
> > > > EDKII_IOMMU_ACCESS_WRITE,
> > > > mVtdUnitInformation[VtdIndex].Is5LevelPaging);
> > > > }
> > > >
> > > > SecondLevelPagingEntry =
> > > > mVtdUnitInformation[VtdIndex].FixedSecondLevelPagingEntry;
> > > > diff --git
> > > >
> >
> a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTableEx.
> > > > c
> > > >
> >
> b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTableEx.
> > > > c
> > > > index 0ed9e3ca..3918eeee 100644
> > > > ---
> > > >
> >
> a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTableEx.
> > > > c
> > > > +++
> > > >
> >
> b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTableEx.
> > > > c
> > > > @@ -78,11 +78,32 @@ CreateExtContextEntry (
> > > >
> > > > DEBUG ((DEBUG_INFO,"DOMAIN: S%04x, B%02x D%02x F%02x\n",
> > > > mVtdUnitInformation[VtdIndex].Segment, SourceId.Bits.Bus,
> > > > SourceId.Bits.Device, SourceId.Bits.Function));
> > > >
> > > > - if ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW & BIT2) == 0)
> > {
> > > > - DEBUG((DEBUG_ERROR, "!!!! 4-level page-table is not supported on
> > > > VTD %d !!!!\n", VtdIndex));
> > > > + mVtdUnitInformation[VtdIndex].Is5LevelPaging = FALSE;
> > > > + if ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW & BIT3) != 0)
> > {
> > > > + if ((PcdGet8(PcdVTdPolicyPropertyMask) & BIT3) != 0) {
> > > > + DEBUG((DEBUG_ERROR, "Force to use 4-level page-table on VTD
> > > > + %d\n",
> > > > VtdIndex));
> > > > + ExtContextEntry->Bits.AddressWidth = 0x2;
> > > > + } if ((PcdGet8(PcdVTdPolicyPropertyMask) & BIT4) != 0) {
> > > > + DEBUG((DEBUG_ERROR, "Force to use 5-level page-table on VTD
> > > > + %d\n",
> > > > VtdIndex));
> > > > + ExtContextEntry->Bits.AddressWidth = 0x3;
> > > > + mVtdUnitInformation[VtdIndex].Is5LevelPaging = TRUE;
> > > > + } else {
> > > > + if (mAcpiDmarTable->HostAddressWidth > 48) {
> > > > + DEBUG((DEBUG_ERROR, "Using 5-level page-table on VTD %d\n",
> > > > VtdIndex));
> > > > + ExtContextEntry->Bits.AddressWidth = 0x3;
> > > > + mVtdUnitInformation[VtdIndex].Is5LevelPaging = TRUE;
> > > > + } else {
> > > > + DEBUG((DEBUG_ERROR, "Using 4-level page-table on VTD %d\n",
> > > > VtdIndex));
> > > > + ExtContextEntry->Bits.AddressWidth = 0x2;
> > > > + }
> > > > + }
> > > > + } else if ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW &
> > > > + BIT2) !=
> > > > 0) {
> > > > + DEBUG((DEBUG_ERROR, "Using 4-level page-table on VTD %d\n",
> > > > VtdIndex));
> > > > + ExtContextEntry->Bits.AddressWidth = 0x2;
> > > > + } else {
> > > > + DEBUG((DEBUG_ERROR, "!!!! Page-table type is not supported on
> > > > VTD %d !!!!\n", VtdIndex));
> > > > return EFI_UNSUPPORTED;
> > > > }
> > > > - ExtContextEntry->Bits.AddressWidth = 0x2;
> > > > }
> > > >
> > > > FlushPageTableMemory (VtdIndex,
> > > > (UINTN)mVtdUnitInformation[VtdIndex].ExtRootEntryTable,
> > > > EFI_PAGES_TO_SIZE(EntryTablePages));
> > > > @@ -93,11 +114,13 @@ CreateExtContextEntry (
> > > > /**
> > > > Dump DMAR extended context entry table.
> > > >
> > > > - @param[in] ExtRootEntry DMAR extended root entry.
> > > > + @param[in] ExtRootEntry DMAR extended root entry.
> > > > + @param[in] Is5LevelPaging If it is the 5 level paging.
> > > > **/
> > > > VOID
> > > > DumpDmarExtContextEntryTable (
> > > > - IN VTD_EXT_ROOT_ENTRY *ExtRootEntry
> > > > + IN VTD_EXT_ROOT_ENTRY *ExtRootEntry, IN BOOLEAN
> Is5LevelPaging
> > > > )
> > > > {
> > > > UINTN Index;
> > > > @@ -127,7 +150,7 @@ DumpDmarExtContextEntryTable (
> > > > if (ExtContextEntry[Index2].Bits.Present == 0) {
> > > > continue;
> > > > }
> > > > - DumpSecondLevelPagingEntry ((VOID
> > > >
> >
> *)(UINTN)VTD_64BITS_ADDRESS(ExtContextEntry[Index2].Bits.SecondLevelPa
> > > > geTranslationPointerLo,
> > > > ExtContextEntry[Index2].Bits.SecondLevelPageTranslationPointerHi));
> > > > + DumpSecondLevelPagingEntry ((VOID
> > > >
> >
> *)(UINTN)VTD_64BITS_ADDRESS(ExtContextEntry[Index2].Bits.SecondLevelPa
> > > > geTranslationPointerLo,
> > > > ExtContextEntry[Index2].Bits.SecondLevelPageTranslationPointerHi),
> > > > Is5LevelPaging);
> > > > }
> > > >
> > > > if (ExtRootEntry[Index].Bits.UpperPresent == 0) { diff --git
> > > > a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/VtdReg.c
> > > > b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/VtdReg.c
> > > > index 699639ba..686d235f 100644
> > > > --- a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/VtdReg.c
> > > > +++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/VtdReg.c
> > > > @@ -174,8 +174,14 @@ PrepareVtdConfig (
> > > > if ((mVtdUnitInformation[Index].CapReg.Bits.SLLPS & BIT0) == 0) {
> > > > DEBUG((DEBUG_WARN, "!!!! 2MB super page is not supported on
> > VTD
> > > > %d !!!!\n", Index));
> > > > }
> > > > - if ((mVtdUnitInformation[Index].CapReg.Bits.SAGAW & BIT2) == 0) {
> > > > - DEBUG((DEBUG_ERROR, "!!!! 4-level page-table is not supported on
> > > > VTD %d !!!!\n", Index));
> > > > + if ((mVtdUnitInformation[Index].CapReg.Bits.SAGAW & BIT3) != 0) {
> > > > + DEBUG((DEBUG_INFO, "Support 5-level page-table on VTD %d\n",
> > > > Index));
> > > > + }
> > > > + if ((mVtdUnitInformation[Index].CapReg.Bits.SAGAW & BIT2) != 0) {
> > > > + DEBUG((DEBUG_INFO, "Support 4-level page-table on VTD %d\n",
> > > > Index));
> > > > + }
> > > > + if ((mVtdUnitInformation[Index].CapReg.Bits.SAGAW & (BIT3 |
> > > > + BIT2)) == 0)
> > > > {
> > > > + DEBUG((DEBUG_ERROR, "!!!! Page-table type 0x%X is not
> supported
> > > > + on
> > > > VTD %d !!!!\n", Index,
> mVtdUnitInformation[Index].CapReg.Bits.SAGAW));
> > > > return ;
> > > > }
> > > >
> > > > diff --git a/Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dec
> > > > b/Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dec
> > > > index 284820af..8f1edfe2 100644
> > > > --- a/Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dec
> > > > +++ b/Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dec
> > > > @@ -95,6 +95,9 @@
> > > > # BIT0: Enable IOMMU during boot (If DMAR table is installed in
> > > > DXE. If VTD_INFO_PPI is installed in PEI.)
> > > > # BIT1: Enable IOMMU when transfer control to OS (ExitBootService
> > > > in normal boot. EndOfPEI in S3)
> > > > # BIT2: Force no IOMMU access attribute request recording before
> > > > DMAR table is installed.
> > > > + # BIT3: Force to use 4 level paging.
> > > > + # BIT4: If iommu support 5 level paging, force to use 5 level paging.
> > > > + # (If both BIT3 and BIT4 are set, force to use 4 level paging.)
> > > > # @Prompt The policy for VTd driver behavior.
> > > >
> > > >
> >
> gIntelSiliconPkgTokenSpaceGuid.PcdVTdPolicyPropertyMask|1|UINT8|0x000
> > > > 00002
> > > >
> > > > --
> > > > 2.16.2.windows.1
>
>
>
>
>
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [edk2-devel] [PATCH v3] IntelSiliconPkg/VTd: Add iommu 5 level paging support
2020-11-18 3:03 ` [edk2-devel] " Yao, Jiewen
@ 2020-11-23 8:10 ` Sheng Wei
0 siblings, 0 replies; 6+ messages in thread
From: Sheng Wei @ 2020-11-23 8:10 UTC (permalink / raw)
To: Yao, Jiewen, devel@edk2.groups.io, Ni, Ray, Huang, Jenny,
Chaganty, Rangasai V
Hi All,
I have updated the patch for support iommu 5 level paging.
Could you help to review the V4 patch ?
https://edk2.groups.io/g/devel/message/67792?p=,,,20,0,0,0::relevance,,posterid%3A2558558,20,2,0,78449079
Thank you.
BR
Sheng Wei
> -----Original Message-----
> From: Yao, Jiewen <jiewen.yao@intel.com>
> Sent: 2020年11月18日 11:04
> To: devel@edk2.groups.io; Yao, Jiewen <jiewen.yao@intel.com>; Sheng, W
> <w.sheng@intel.com>
> Cc: Ni, Ray <ray.ni@intel.com>; Chaganty, Rangasai V
> <rangasai.v.chaganty@intel.com>; Huang, Jenny <jenny.huang@intel.com>
> Subject: RE: [edk2-devel] [PATCH v3] IntelSiliconPkg/VTd: Add iommu 5 level
> paging support
>
> Just checked PISMM CPU driver, which use below code to decide if 5 level
> paging is needed.
> https://github.com/tianocore/edk2/blob/master/UefiCpuPkg/PiSmmCpuDxeSm
> m/X64/PageTbl.c#L75
>
> Can we use the similar algorithm? It just includes check for :
> 1) Hardware Capability
> 2) Hardware Address Range
> 3) Software Execution Mode
>
> And it can be done automatically.
>
> ===================
> BOOLEAN
> Is5LevelPagingNeeded (
> VOID
> )
> {
> CPUID_VIR_PHY_ADDRESS_SIZE_EAX VirPhyAddressSize;
> CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS_ECX ExtFeatureEcx;
> UINT32 MaxExtendedFunctionId;
>
> AsmCpuid (CPUID_EXTENDED_FUNCTION, &MaxExtendedFunctionId, NULL,
> NULL, NULL);
> if (MaxExtendedFunctionId >= CPUID_VIR_PHY_ADDRESS_SIZE) {
> AsmCpuid (CPUID_VIR_PHY_ADDRESS_SIZE, &VirPhyAddressSize.Uint32,
> NULL, NULL, NULL);
> } else {
> VirPhyAddressSize.Bits.PhysicalAddressBits = 36;
> }
> AsmCpuidEx (
> CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS,
> CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS_SUB_LEAF_INFO,
> NULL, NULL, &ExtFeatureEcx.Uint32, NULL
> );
> DEBUG ((
> DEBUG_INFO, "PhysicalAddressBits = %d, 5LPageTable = %d.\n",
> VirPhyAddressSize.Bits.PhysicalAddressBits, ExtFeatureEcx.Bits.FiveLevelPage
> ));
>
> if (VirPhyAddressSize.Bits.PhysicalAddressBits > 4 * 9 + 12) {
> ASSERT (ExtFeatureEcx.Bits.FiveLevelPage == 1);
> return TRUE;
> } else {
> return FALSE;
> }
> }
>
> > -----Original Message-----
> > From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Yao,
> > Jiewen
> > Sent: Wednesday, November 18, 2020 10:49 AM
> > To: Sheng, W <w.sheng@intel.com>; devel@edk2.groups.io
> > Cc: Ni, Ray <ray.ni@intel.com>; Chaganty, Rangasai V
> > <rangasai.v.chaganty@intel.com>; Huang, Jenny <jenny.huang@intel.com>
> > Subject: Re: [edk2-devel] [PATCH v3] IntelSiliconPkg/VTd: Add iommu 5 level
> > paging support
> >
> > Sorry I did not say clearly.
> >
> > 1) I mean the (SAGAW & BIT2) check should also happen inside of (SAGAW &
> > BIT3), the first if.
> >
> > Otherwise, the logic is:
> >
> > If (5 level support) {
> > If (need 4 level) {
> > Do 4 level
> > }
> > }
> >
> > That is odd.
> >
> > 2) In general, I recommend we have a better way to manage test/debug code
> > into production. The PCD should be used when it is absolutely necessary.
> > I think the policy should be as simple as possible. Otherwise, the production
> > team wont know how to choose.
> >
> >
> > > -----Original Message-----
> > > From: Sheng, W <w.sheng@intel.com>
> > > Sent: Wednesday, November 18, 2020 10:33 AM
> > > To: Yao, Jiewen <jiewen.yao@intel.com>; devel@edk2.groups.io
> > > Cc: Ni, Ray <ray.ni@intel.com>; Chaganty, Rangasai V
> > > <rangasai.v.chaganty@intel.com>; Huang, Jenny <jenny.huang@intel.com>
> > > Subject: RE: [PATCH v3] IntelSiliconPkg/VTd: Add iommu 5 level paging
> > > support
> > >
> > > Hi Jeiwen,
> > > For comment 1:
> > > The code about (SAGAW & BIT2) is just behand (SAGAW & BIT3)
> > >
> > > > > + DEBUG((DEBUG_ERROR, "Using 4-level page-table on
> VTD %d\n",
> > > > > VtdIndex));
> > > > > + ExtContextEntry->Bits.AddressWidth = 0x2;
> > > > > + }
> > > > > + }
> > > > > + } else if ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW &
> > > > > + BIT2) !=
> > > > > 0) {
> > > > > + DEBUG((DEBUG_ERROR, "Using 4-level page-table on VTD %d\n",
> > > > > VtdIndex));
> > > > > + ExtContextEntry->Bits.AddressWidth = 0x2;
> > > > > + } else {
> > > > > + DEBUG((DEBUG_ERROR, "!!!! Page-table type is not supported on
> > > > > VTD %d !!!!\n", VtdIndex));
> > > > > return EFI_UNSUPPORTED;
> > > > > }
> > > > > - ExtContextEntry->Bits.AddressWidth = 0x2;
> > > > > }
> > >
> > > For comment 2:
> > > > # BIT3: Force to use 4 level paging.
> > > > # BIT4: If iommu support 5 level paging, force to use 5 level paging.
> > > > # (If both BIT3 and BIT4 are set, force to use 4 level paging.)
> > > Mostly, these 2 bits are for debug/test purpose, it could be used to force
> > the
> > > page table depth.
> > > Do you think it is no necessary? Or we could find another solution ?
> > >
> > > Thank you
> > > BR
> > > Sheng Wei
> > >
> > >
> > > > -----Original Message-----
> > > > From: Yao, Jiewen <jiewen.yao@intel.com>
> > > > Sent: 2020年11月18日 9:39
> > > > To: Sheng, W <w.sheng@intel.com>; devel@edk2.groups.io
> > > > Cc: Ni, Ray <ray.ni@intel.com>; Chaganty, Rangasai V
> > > > <rangasai.v.chaganty@intel.com>; Huang, Jenny
> > <jenny.huang@intel.com>
> > > > Subject: RE: [PATCH v3] IntelSiliconPkg/VTd: Add iommu 5 level paging
> > > support
> > > >
> > > > Hi
> > > > I have 2 comments:
> > > >
> > > > 1) below capability check seems not correct.
> > > >
> > > > (SAGAW & BIT3) is for 5 level only.
> > > > We need check (SAGAW & BIT2) for 4 level. But I do not see the code. Do I
> > > miss
> > > > something?
> > > >
> > > > if ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW & BIT3) != 0) {
> > > > if ((PcdGet8(PcdVTdPolicyPropertyMask) & BIT3) != 0) {
> > > > DEBUG((DEBUG_ERROR, "Force to use 4-level page-table on
> > > VTD %d\n",
> > > > VtdIndex));
> > > > ContextEntry->Bits.AddressWidth = 0x2;
> > > > } if ((PcdGet8(PcdVTdPolicyPropertyMask) & BIT4) != 0) {
> > > > DEBUG((DEBUG_ERROR, "Force to use 5-level page-table on
> > > VTD %d\n",
> > > > VtdIndex));
> > > > ContextEntry->Bits.AddressWidth = 0x3;
> > > > mVtdUnitInformation[VtdIndex].Is5LevelPaging = TRUE;
> > > > } else {
> > > > if (mAcpiDmarTable->HostAddressWidth > 48) {
> > > > DEBUG((DEBUG_ERROR, "Using 5-level page-table on VTD %d\n",
> > > > VtdIndex));
> > > > ContextEntry->Bits.AddressWidth = 0x3;
> > > > mVtdUnitInformation[VtdIndex].Is5LevelPaging = TRUE;
> > > > } else {
> > > > DEBUG((DEBUG_ERROR, "Using 4-level page-table on VTD %d\n",
> > > > VtdIndex));
> > > > ContextEntry->Bits.AddressWidth = 0x2;
> > > > }
> > > > }
> > > >
> > > > 2) I am wondering, do we really need 2 bit for level selection ?
> > > > What if force 4 level, but the platform does not support?
> > > > What if force 5 level, but the platform does not support?
> > > >
> > > > # BIT3: Force to use 4 level paging.
> > > > # BIT4: If iommu support 5 level paging, force to use 5 level paging.
> > > > # (If both BIT3 and BIT4 are set, force to use 4 level paging.)
> > > >
> > > >
> > >
> > gIntelSiliconPkgTokenSpaceGuid.PcdVTdPolicyPropertyMask|1|UINT8|0x000
> > > 00
> > > > 002
> > > >
> > > > Can we align the solution in DXE/SMM paging solution?
> > > >
> > > >
> > > >
> > > > > -----Original Message-----
> > > > > From: Sheng, W <w.sheng@intel.com>
> > > > > Sent: Wednesday, November 18, 2020 9:18 AM
> > > > > To: devel@edk2.groups.io
> > > > > Cc: Ni, Ray <ray.ni@intel.com>; Chaganty, Rangasai V
> > > > > <rangasai.v.chaganty@intel.com>; Yao, Jiewen <jiewen.yao@intel.com>;
> > > > > Huang, Jenny <jenny.huang@intel.com>
> > > > > Subject: [PATCH v3] IntelSiliconPkg/VTd: Add iommu 5 level paging
> > > > > support
> > > > >
> > > > > Support iommu 5 level paging for translation table.
> > > > >
> > > > > REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3067
> > > > >
> > > > > 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: Jiewen Yao <jiewen.yao@intel.com>
> > > > > Cc: Jenny Huang <jenny.huang@intel.com>
> > > > > ---
> > > > > .../Feature/VTd/IntelVTdDxe/DmaProtection.c | 4 +-
> > > > > .../Feature/VTd/IntelVTdDxe/DmaProtection.h | 19 +-
> > > > > .../Feature/VTd/IntelVTdDxe/TranslationTable.c | 287
> > > +++++++++++++++--
> > > > > ----
> > > > > .../Feature/VTd/IntelVTdDxe/TranslationTableEx.c | 35 ++-
> > > > > .../Feature/VTd/IntelVTdDxe/VtdReg.c | 10 +-
> > > > > Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dec | 3 +
> > > > > 6 files changed, 258 insertions(+), 100 deletions(-)
> > > > >
> > > > > diff --git
> > > > >
> > a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.
> > > > > c
> > > > >
> > b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.
> > > > > c
> > > > > index 9b6135ef..628565ee 100644
> > > > > ---
> > > > >
> > a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.
> > > > > c
> > > > > +++
> > > > >
> > b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.
> > > > > c
> > > > > @@ -523,10 +523,10 @@ SetupVtd (
> > > > > for (Index = 0; Index < mVtdUnitNumber; Index++) {
> > > > > DEBUG ((DEBUG_INFO,"VTD Unit %d (Segment: %04x)\n", Index,
> > > > > mVtdUnitInformation[Index].Segment));
> > > > > if (mVtdUnitInformation[Index].ExtRootEntryTable != NULL) {
> > > > > - DumpDmarExtContextEntryTable
> > > > > (mVtdUnitInformation[Index].ExtRootEntryTable);
> > > > > + DumpDmarExtContextEntryTable
> > > > > (mVtdUnitInformation[Index].ExtRootEntryTable,
> > > > > mVtdUnitInformation[Index].Is5LevelPaging);
> > > > > }
> > > > > if (mVtdUnitInformation[Index].RootEntryTable != NULL) {
> > > > > - DumpDmarContextEntryTable
> > > > > (mVtdUnitInformation[Index].RootEntryTable);
> > > > > + DumpDmarContextEntryTable
> > > > > (mVtdUnitInformation[Index].RootEntryTable,
> > > > > mVtdUnitInformation[Index].Is5LevelPaging);
> > > > > }
> > > > > }
> > > > >
> > > > > diff --git
> > > > >
> > a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.
> > > > > h
> > > > >
> > b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.
> > > > > h
> > > > > index a3331db8..f641cea0 100644
> > > > > ---
> > > > >
> > a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.
> > > > > h
> > > > > +++
> > > > >
> > b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.
> > > > > h
> > > > > @@ -77,6 +77,7 @@ typedef struct {
> > > > > BOOLEAN HasDirtyContext;
> > > > > BOOLEAN HasDirtyPages;
> > > > > PCI_DEVICE_INFORMATION PciDeviceInfo;
> > > > > + BOOLEAN Is5LevelPaging;
> > > > > } VTD_UNIT_INFORMATION;
> > > > >
> > > > > //
> > > > > @@ -375,31 +376,37 @@ ParseDmarAcpiTableRmrr (
> > > > > /**
> > > > > Dump DMAR context entry table.
> > > > >
> > > > > - @param[in] RootEntry DMAR root entry.
> > > > > + @param[in] RootEntry DMAR root entry.
> > > > > + @param[in] Is5LevelPaging If it is the 5 level paging.
> > > > > **/
> > > > > VOID
> > > > > DumpDmarContextEntryTable (
> > > > > - IN VTD_ROOT_ENTRY *RootEntry
> > > > > + IN VTD_ROOT_ENTRY *RootEntry,
> > > > > + IN BOOLEAN Is5LevelPaging
> > > > > );
> > > > >
> > > > > /**
> > > > > Dump DMAR extended context entry table.
> > > > >
> > > > > - @param[in] ExtRootEntry DMAR extended root entry.
> > > > > + @param[in] ExtRootEntry DMAR extended root entry.
> > > > > + @param[in] Is5LevelPaging If it is the 5 level paging.
> > > > > **/
> > > > > VOID
> > > > > DumpDmarExtContextEntryTable (
> > > > > - IN VTD_EXT_ROOT_ENTRY *ExtRootEntry
> > > > > + IN VTD_EXT_ROOT_ENTRY *ExtRootEntry, IN BOOLEAN
> > Is5LevelPaging
> > > > > );
> > > > >
> > > > > /**
> > > > > Dump DMAR second level paging entry.
> > > > >
> > > > > - @param[in] SecondLevelPagingEntry The second level paging entry.
> > > > > + @param[in] SecondLevelPagingEntry The second level paging entry.
> > > > > + @param[in] Is5LevelPaging If it is the 5 level paging.
> > > > > **/
> > > > > VOID
> > > > > DumpSecondLevelPagingEntry (
> > > > > - IN VOID *SecondLevelPagingEntry
> > > > > + IN VOID *SecondLevelPagingEntry,
> > > > > + IN BOOLEAN Is5LevelPaging
> > > > > );
> > > > >
> > > > > /**
> > > > > diff --git
> > > > >
> > a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTab
> > > > > le.c
> > > > >
> > b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTab
> > > > > le.c
> > > > > index 201d663d..cb59860a 100644
> > > > > ---
> > > > >
> > a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTab
> > > > > le.c
> > > > > +++
> > > > >
> > b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTab
> > > > > le.c @@ -128,11 +128,32 @@ CreateContextEntry (
> > > > >
> > > > > DEBUG ((DEBUG_INFO,"Source: S%04x B%02x D%02x F%02x\n",
> > > > > mVtdUnitInformation[VtdIndex].Segment, SourceId.Bits.Bus,
> > > > > SourceId.Bits.Device, SourceId.Bits.Function));
> > > > >
> > > > > - if ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW & BIT2) == 0)
> > > {
> > > > > - DEBUG((DEBUG_ERROR, "!!!! 4-level page-table is not supported on
> > > > > VTD %d !!!!\n", VtdIndex));
> > > > > + mVtdUnitInformation[VtdIndex].Is5LevelPaging = FALSE;
> > > > > + if ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW & BIT3) != 0)
> > > {
> > > > > + if ((PcdGet8(PcdVTdPolicyPropertyMask) & BIT3) != 0) {
> > > > > + DEBUG((DEBUG_ERROR, "Force to use 4-level page-table on VTD
> > > > > + %d\n",
> > > > > VtdIndex));
> > > > > + ContextEntry->Bits.AddressWidth = 0x2;
> > > > > + } if ((PcdGet8(PcdVTdPolicyPropertyMask) & BIT4) != 0) {
> > > > > + DEBUG((DEBUG_ERROR, "Force to use 5-level page-table on VTD
> > > > > + %d\n",
> > > > > VtdIndex));
> > > > > + ContextEntry->Bits.AddressWidth = 0x3;
> > > > > + mVtdUnitInformation[VtdIndex].Is5LevelPaging = TRUE;
> > > > > + } else {
> > > > > + if (mAcpiDmarTable->HostAddressWidth > 48) {
> > > > > + DEBUG((DEBUG_ERROR, "Using 5-level page-table on
> VTD %d\n",
> > > > > VtdIndex));
> > > > > + ContextEntry->Bits.AddressWidth = 0x3;
> > > > > + mVtdUnitInformation[VtdIndex].Is5LevelPaging = TRUE;
> > > > > + } else {
> > > > > + DEBUG((DEBUG_ERROR, "Using 4-level page-table on
> VTD %d\n",
> > > > > VtdIndex));
> > > > > + ContextEntry->Bits.AddressWidth = 0x2;
> > > > > + }
> > > > > + }
> > > > > + } else if ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW &
> > > > > + BIT2) !=
> > > > > 0) {
> > > > > + DEBUG((DEBUG_ERROR, "Using 4-level page-table on VTD %d\n",
> > > > > VtdIndex));
> > > > > + ContextEntry->Bits.AddressWidth = 0x2;
> > > > > + } else {
> > > > > + DEBUG((DEBUG_ERROR, "!!!! Page-table type is not supported on
> > > > > VTD %d !!!!\n", VtdIndex));
> > > > > return EFI_UNSUPPORTED;
> > > > > }
> > > > > - ContextEntry->Bits.AddressWidth = 0x2;
> > > > > }
> > > > >
> > > > > FlushPageTableMemory (VtdIndex,
> > > > > (UINTN)mVtdUnitInformation[VtdIndex].RootEntryTable,
> > > > > EFI_PAGES_TO_SIZE(EntryTablePages));
> > > > > @@ -148,6 +169,7 @@ CreateContextEntry (
> > > > > @param[in] MemoryBase The base of the memory.
> > > > > @param[in] MemoryLimit The limit of the memory.
> > > > > @param[in] IoMmuAccess The IOMMU access.
> > > > > + @param[in] Is5LevelPaging If it is the 5 level paging.
> > > > >
> > > > > @return The second level paging entry.
> > > > > **/
> > > > > @@ -157,16 +179,23 @@ CreateSecondLevelPagingEntryTable (
> > > > > IN VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry,
> > > > > IN UINT64 MemoryBase,
> > > > > IN UINT64 MemoryLimit,
> > > > > - IN UINT64 IoMmuAccess
> > > > > + IN UINT64 IoMmuAccess,
> > > > > + IN BOOLEAN Is5LevelPaging
> > > > > )
> > > > > {
> > > > > + UINTN Index5;
> > > > > UINTN Index4;
> > > > > UINTN Index3;
> > > > > UINTN Index2;
> > > > > + UINTN Lvl5Start;
> > > > > + UINTN Lvl5End;
> > > > > + UINTN Lvl4PagesStart;
> > > > > + UINTN Lvl4PagesEnd;
> > > > > UINTN Lvl4Start;
> > > > > UINTN Lvl4End;
> > > > > UINTN Lvl3Start;
> > > > > UINTN Lvl3End;
> > > > > + VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl5PtEntry;
> > > > > VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl4PtEntry;
> > > > > VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl3PtEntry;
> > > > > VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl2PtEntry; @@ -184,7
> > +213,7
> > > > @@
> > > > > CreateSecondLevelPagingEntryTable (
> > > > > if (SecondLevelPagingEntry == NULL) {
> > > > > SecondLevelPagingEntry = AllocateZeroPages (1);
> > > > > if (SecondLevelPagingEntry == NULL) {
> > > > > - DEBUG ((DEBUG_ERROR,"Could not Alloc LVL4 PT. \n"));
> > > > > + DEBUG ((DEBUG_ERROR,"Could not Alloc LVL4 or LVL5 PT. \n"));
> > > > > return NULL;
> > > > > }
> > > > > FlushPageTableMemory (VtdIndex, (UINTN)SecondLevelPagingEntry,
> > > > > EFI_PAGES_TO_SIZE(1)); @@ -197,66 +226,109 @@
> > > > > CreateSecondLevelPagingEntryTable (
> > > > > return SecondLevelPagingEntry;
> > > > > }
> > > > >
> > > > > - Lvl4Start = RShiftU64 (BaseAddress, 39) & 0x1FF;
> > > > > - Lvl4End = RShiftU64 (EndAddress - 1, 39) & 0x1FF;
> > > > > + if (Is5LevelPaging) {
> > > > > + Lvl5Start = RShiftU64 (BaseAddress, 48) & 0x1FF;
> > > > > + Lvl5End = RShiftU64 (EndAddress - 1, 48) & 0x1FF;
> > > > > + DEBUG ((DEBUG_INFO," Lvl5Start - 0x%x, Lvl5End - 0x%x\n",
> > > > > + Lvl5Start,
> > > > > Lvl5End));
> > > > >
> > > > > - DEBUG ((DEBUG_INFO," Lvl4Start - 0x%x, Lvl4End - 0x%x\n",
> > > > > Lvl4Start, Lvl4End));
> > > > > + Lvl4Start = RShiftU64 (BaseAddress, 39) & 0x1FF;
> > > > > + Lvl4End = RShiftU64 (EndAddress - 1, 39) & 0x1FF;
> > > > >
> > > > > - Lvl4PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> > > > > *)SecondLevelPagingEntry;
> > > > > - for (Index4 = Lvl4Start; Index4 <= Lvl4End; Index4++) {
> > > > > - if (Lvl4PtEntry[Index4].Uint64 == 0) {
> > > > > - Lvl4PtEntry[Index4].Uint64 = (UINT64)(UINTN)AllocateZeroPages (1);
> > > > > - if (Lvl4PtEntry[Index4].Uint64 == 0) {
> > > > > - DEBUG ((DEBUG_ERROR,"!!!!!! ALLOCATE LVL4 PAGE FAIL
> > > > > (0x%x)!!!!!!\n", Index4));
> > > > > - ASSERT(FALSE);
> > > > > - return NULL;
> > > > > - }
> > > > > - FlushPageTableMemory (VtdIndex,
> > > (UINTN)Lvl4PtEntry[Index4].Uint64,
> > > > > SIZE_4KB);
> > > > > - SetSecondLevelPagingEntryAttribute (&Lvl4PtEntry[Index4],
> > > > > EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);
> > > > > - }
> > > > > + Lvl4PagesStart = (Lvl5Start<<9) | Lvl4Start;
> > > > > + Lvl4PagesEnd = (Lvl5End<<9) | Lvl4End;
> > > > > + DEBUG ((DEBUG_INFO," Lvl4PagesStart - 0x%x, Lvl4PagesEnd -
> > > > > + 0x%x\n",
> > > > > Lvl4PagesStart, Lvl4PagesEnd));
> > > > >
> > > > > - Lvl3Start = RShiftU64 (BaseAddress, 30) & 0x1FF;
> > > > > - if (ALIGN_VALUE_LOW(BaseAddress + SIZE_1GB, SIZE_1GB) <=
> > > > > EndAddress) {
> > > > > - Lvl3End = SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY) -
> 1;
> > > > > - } else {
> > > > > - Lvl3End = RShiftU64 (EndAddress - 1, 30) & 0x1FF;
> > > > > + Lvl5PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> > > > > *)SecondLevelPagingEntry;
> > > > > + } else {
> > > > > + Lvl5Start = RShiftU64 (BaseAddress, 48) & 0x1FF;
> > > > > + Lvl5End = Lvl5Start;
> > > > > +
> > > > > + Lvl4Start = RShiftU64 (BaseAddress, 39) & 0x1FF;
> > > > > + Lvl4End = RShiftU64 (EndAddress - 1, 39) & 0x1FF;
> > > > > + DEBUG ((DEBUG_INFO," Lvl4Start - 0x%x, Lvl4End - 0x%x\n",
> > > > > + Lvl4Start,
> > > > > Lvl4End));
> > > > > +
> > > > > + Lvl4PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> > > > > *)SecondLevelPagingEntry;
> > > > > + }
> > > > > +
> > > > > + for (Index5 = Lvl5Start; Index5 <= Lvl5End; Index5++) {
> > > > > + if (Is5LevelPaging) {
> > > > > + if (Lvl5PtEntry[Index5].Uint64 == 0) {
> > > > > + Lvl5PtEntry[Index5].Uint64 = (UINT64)(UINTN)AllocateZeroPages
> > (1);
> > > > > + if (Lvl5PtEntry[Index5].Uint64 == 0) {
> > > > > + DEBUG ((DEBUG_ERROR,"!!!!!! ALLOCATE LVL4 PAGE FAIL
> > > > > (0x%x)!!!!!!\n", Index5));
> > > > > + ASSERT(FALSE);
> > > > > + return NULL;
> > > > > + }
> > > > > + FlushPageTableMemory (VtdIndex,
> > > > > + (UINTN)Lvl5PtEntry[Index5].Uint64,
> > > > > SIZE_4KB);
> > > > > + SetSecondLevelPagingEntryAttribute (&Lvl5PtEntry[Index5],
> > > > > EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);
> > > > > + }
> > > > > + Lvl4Start = Lvl4PagesStart & 0x1FF;
> > > > > + if (((Index5+1)<<9) > Lvl4PagesEnd) {
> > > > > + Lvl4End = SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY)
> -
> > > 1;;
> > > > > + Lvl4PagesStart = (Index5+1)<<9;
> > > > > + } else {
> > > > > + Lvl4End = Lvl4PagesEnd & 0x1FF;
> > > > > + }
> > > > > + DEBUG ((DEBUG_INFO," Lvl5(0x%x): Lvl4Start - 0x%x, Lvl4End -
> > > > > + 0x%x\n",
> > > > > Index5, Lvl4Start, Lvl4End));
> > > > > + Lvl4PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> > > > > *)(UINTN)VTD_64BITS_ADDRESS(Lvl5PtEntry[Index5].Bits.AddressLo,
> > > > > Lvl5PtEntry[Index5].Bits.AddressHi);
> > > > > }
> > > > > - DEBUG ((DEBUG_INFO," Lvl4(0x%x): Lvl3Start - 0x%x, Lvl3End -
> > > 0x%x\n",
> > > > > Index4, Lvl3Start, Lvl3End));
> > > > >
> > > > > - Lvl3PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> > > > > *)(UINTN)VTD_64BITS_ADDRESS(Lvl4PtEntry[Index4].Bits.AddressLo,
> > > > > Lvl4PtEntry[Index4].Bits.AddressHi);
> > > > > - for (Index3 = Lvl3Start; Index3 <= Lvl3End; Index3++) {
> > > > > - if (Lvl3PtEntry[Index3].Uint64 == 0) {
> > > > > - Lvl3PtEntry[Index3].Uint64 = (UINT64)(UINTN)AllocateZeroPages
> > (1);
> > > > > - if (Lvl3PtEntry[Index3].Uint64 == 0) {
> > > > > - DEBUG ((DEBUG_ERROR,"!!!!!! ALLOCATE LVL3 PAGE FAIL (0x%x,
> > > > > 0x%x)!!!!!!\n", Index4, Index3));
> > > > > + for (Index4 = Lvl4Start; Index4 <= Lvl4End; Index4++) {
> > > > > + if (Lvl4PtEntry[Index4].Uint64 == 0) {
> > > > > + Lvl4PtEntry[Index4].Uint64 = (UINT64)(UINTN)AllocateZeroPages
> > (1);
> > > > > + if (Lvl4PtEntry[Index4].Uint64 == 0) {
> > > > > + DEBUG ((DEBUG_ERROR,"!!!!!! ALLOCATE LVL4 PAGE FAIL
> > > > > (0x%x)!!!!!!\n", Index4));
> > > > > ASSERT(FALSE);
> > > > > return NULL;
> > > > > }
> > > > > - FlushPageTableMemory (VtdIndex,
> > > (UINTN)Lvl3PtEntry[Index3].Uint64,
> > > > > SIZE_4KB);
> > > > > - SetSecondLevelPagingEntryAttribute (&Lvl3PtEntry[Index3],
> > > > > EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);
> > > > > + FlushPageTableMemory (VtdIndex,
> > > > > + (UINTN)Lvl4PtEntry[Index4].Uint64,
> > > > > SIZE_4KB);
> > > > > + SetSecondLevelPagingEntryAttribute (&Lvl4PtEntry[Index4],
> > > > > EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);
> > > > > }
> > > > >
> > > > > - Lvl2PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> > > > > *)(UINTN)VTD_64BITS_ADDRESS(Lvl3PtEntry[Index3].Bits.AddressLo,
> > > > > Lvl3PtEntry[Index3].Bits.AddressHi);
> > > > > - for (Index2 = 0; Index2 <
> > > > > SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY); Index2++) {
> > > > > - Lvl2PtEntry[Index2].Uint64 = BaseAddress;
> > > > > - SetSecondLevelPagingEntryAttribute (&Lvl2PtEntry[Index2],
> > > > > IoMmuAccess);
> > > > > - Lvl2PtEntry[Index2].Bits.PageSize = 1;
> > > > > - BaseAddress += SIZE_2MB;
> > > > > + Lvl3Start = RShiftU64 (BaseAddress, 30) & 0x1FF;
> > > > > + if (ALIGN_VALUE_LOW(BaseAddress + SIZE_1GB, SIZE_1GB) <=
> > > > > EndAddress) {
> > > > > + Lvl3End = SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY)
> -
> > 1;
> > > > > + } else {
> > > > > + Lvl3End = RShiftU64 (EndAddress - 1, 30) & 0x1FF;
> > > > > + }
> > > > > + DEBUG ((DEBUG_INFO," Lvl4(0x%x): Lvl3Start - 0x%x, Lvl3End -
> > > > > + 0x%x\n",
> > > > > Index4, Lvl3Start, Lvl3End));
> > > > > +
> > > > > + Lvl3PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> > > > > *)(UINTN)VTD_64BITS_ADDRESS(Lvl4PtEntry[Index4].Bits.AddressLo,
> > > > > Lvl4PtEntry[Index4].Bits.AddressHi);
> > > > > + for (Index3 = Lvl3Start; Index3 <= Lvl3End; Index3++) {
> > > > > + if (Lvl3PtEntry[Index3].Uint64 == 0) {
> > > > > + Lvl3PtEntry[Index3].Uint64 = (UINT64)(UINTN)AllocateZeroPages
> > > (1);
> > > > > + if (Lvl3PtEntry[Index3].Uint64 == 0) {
> > > > > + DEBUG ((DEBUG_ERROR,"!!!!!! ALLOCATE LVL3 PAGE FAIL
> > > > > + (0x%x,
> > > > > 0x%x)!!!!!!\n", Index4, Index3));
> > > > > + ASSERT(FALSE);
> > > > > + return NULL;
> > > > > + }
> > > > > + FlushPageTableMemory (VtdIndex,
> > > > > + (UINTN)Lvl3PtEntry[Index3].Uint64,
> > > > > SIZE_4KB);
> > > > > + SetSecondLevelPagingEntryAttribute (&Lvl3PtEntry[Index3],
> > > > > EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);
> > > > > + }
> > > > > +
> > > > > + Lvl2PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> > > > > *)(UINTN)VTD_64BITS_ADDRESS(Lvl3PtEntry[Index3].Bits.AddressLo,
> > > > > Lvl3PtEntry[Index3].Bits.AddressHi);
> > > > > + for (Index2 = 0; Index2 <
> > > > > SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY); Index2++) {
> > > > > + Lvl2PtEntry[Index2].Uint64 = BaseAddress;
> > > > > + SetSecondLevelPagingEntryAttribute (&Lvl2PtEntry[Index2],
> > > > > IoMmuAccess);
> > > > > + Lvl2PtEntry[Index2].Bits.PageSize = 1;
> > > > > + BaseAddress += SIZE_2MB;
> > > > > + if (BaseAddress >= MemoryLimit) {
> > > > > + break;
> > > > > + }
> > > > > + }
> > > > > + FlushPageTableMemory (VtdIndex, (UINTN)Lvl2PtEntry,
> > > > > + SIZE_4KB);
> > > > > if (BaseAddress >= MemoryLimit) {
> > > > > break;
> > > > > }
> > > > > }
> > > > > - FlushPageTableMemory (VtdIndex, (UINTN)Lvl2PtEntry, SIZE_4KB);
> > > > > + FlushPageTableMemory (VtdIndex, (UINTN)&Lvl3PtEntry[Lvl3Start],
> > > > > (UINTN)&Lvl3PtEntry[Lvl3End + 1] - (UINTN)&Lvl3PtEntry[Lvl3Start]);
> > > > > if (BaseAddress >= MemoryLimit) {
> > > > > break;
> > > > > }
> > > > > }
> > > > > - FlushPageTableMemory (VtdIndex, (UINTN)&Lvl3PtEntry[Lvl3Start],
> > > > > (UINTN)&Lvl3PtEntry[Lvl3End + 1] - (UINTN)&Lvl3PtEntry[Lvl3Start]);
> > > > > - if (BaseAddress >= MemoryLimit) {
> > > > > - break;
> > > > > - }
> > > > > + FlushPageTableMemory (VtdIndex, (UINTN)&Lvl4PtEntry[Lvl4Start],
> > > > > (UINTN)&Lvl4PtEntry[Lvl4End + 1] - (UINTN)&Lvl4PtEntry[Lvl4Start]);
> > > > > }
> > > > > - FlushPageTableMemory (VtdIndex, (UINTN)&Lvl4PtEntry[Lvl4Start],
> > > > > (UINTN)&Lvl4PtEntry[Lvl4End + 1] - (UINTN)&Lvl4PtEntry[Lvl4Start]);
> > > > > + FlushPageTableMemory (VtdIndex, (UINTN)&Lvl5PtEntry[Lvl5Start],
> > > > > (UINTN)&Lvl5PtEntry[Lvl5End + 1] - (UINTN)&Lvl5PtEntry[Lvl5Start]);
> > > > >
> > > > > return SecondLevelPagingEntry;
> > > > > }
> > > > > @@ -266,26 +338,28 @@ CreateSecondLevelPagingEntryTable (
> > > > >
> > > > > @param[in] VtdIndex The index of the VTd engine.
> > > > > @param[in] IoMmuAccess The IOMMU access.
> > > > > + @param[in] Is5LevelPaging If it is the 5 level paging.
> > > > >
> > > > > @return The second level paging entry.
> > > > > **/
> > > > > VTD_SECOND_LEVEL_PAGING_ENTRY *
> > > > > CreateSecondLevelPagingEntry (
> > > > > IN UINTN VtdIndex,
> > > > > - IN UINT64 IoMmuAccess
> > > > > + IN UINT64 IoMmuAccess,
> > > > > + IN BOOLEAN Is5LevelPaging
> > > > > )
> > > > > {
> > > > > VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry;
> > > > >
> > > > > SecondLevelPagingEntry = NULL;
> > > > > - SecondLevelPagingEntry = CreateSecondLevelPagingEntryTable
> > > > > (VtdIndex, SecondLevelPagingEntry, 0, mBelow4GMemoryLimit,
> > > > > IoMmuAccess);
> > > > > + SecondLevelPagingEntry = CreateSecondLevelPagingEntryTable
> > > > > + (VtdIndex,
> > > > > SecondLevelPagingEntry, 0, mBelow4GMemoryLimit, IoMmuAccess,
> > > > > Is5LevelPaging);
> > > > > if (SecondLevelPagingEntry == NULL) {
> > > > > return NULL;
> > > > > }
> > > > >
> > > > > if (mAbove4GMemoryLimit != 0) {
> > > > > ASSERT (mAbove4GMemoryLimit > BASE_4GB);
> > > > > - SecondLevelPagingEntry = CreateSecondLevelPagingEntryTable
> > > (VtdIndex,
> > > > > SecondLevelPagingEntry, SIZE_4GB, mAbove4GMemoryLimit,
> > > IoMmuAccess);
> > > > > + SecondLevelPagingEntry = CreateSecondLevelPagingEntryTable
> > > > > + (VtdIndex,
> > > > > SecondLevelPagingEntry, SIZE_4GB, mAbove4GMemoryLimit,
> > > IoMmuAccess,
> > > > > Is5LevelPaging);
> > > > > if (SecondLevelPagingEntry == NULL) {
> > > > > return NULL;
> > > > > }
> > > > > @@ -326,11 +400,13 @@ SetupTranslationTable (
> > > > > /**
> > > > > Dump DMAR context entry table.
> > > > >
> > > > > - @param[in] RootEntry DMAR root entry.
> > > > > + @param[in] RootEntry DMAR root entry.
> > > > > + @param[in] Is5LevelPaging If it is the 5 level paging.
> > > > > **/
> > > > > VOID
> > > > > DumpDmarContextEntryTable (
> > > > > - IN VTD_ROOT_ENTRY *RootEntry
> > > > > + IN VTD_ROOT_ENTRY *RootEntry,
> > > > > + IN BOOLEAN Is5LevelPaging
> > > > > )
> > > > > {
> > > > > UINTN Index;
> > > > > @@ -359,7 +435,7 @@ DumpDmarContextEntryTable (
> > > > > if (ContextEntry[Index2].Bits.Present == 0) {
> > > > > continue;
> > > > > }
> > > > > - DumpSecondLevelPagingEntry ((VOID
> > > > >
> > >
> > *)(UINTN)VTD_64BITS_ADDRESS(ContextEntry[Index2].Bits.SecondLevelPage
> > > > > TranslationPointerLo,
> > > > > ContextEntry[Index2].Bits.SecondLevelPageTranslationPointerHi));
> > > > > + DumpSecondLevelPagingEntry ((VOID
> > > > >
> > >
> > *)(UINTN)VTD_64BITS_ADDRESS(ContextEntry[Index2].Bits.SecondLevelPage
> > > > > TranslationPointerLo,
> > > > > ContextEntry[Index2].Bits.SecondLevelPageTranslationPointerHi),
> > > > > Is5LevelPaging);
> > > > > }
> > > > > }
> > > > > DEBUG ((DEBUG_INFO,"=========================\n"));
> > > > > @@ -368,17 +444,22 @@ DumpDmarContextEntryTable (
> > > > > /**
> > > > > Dump DMAR second level paging entry.
> > > > >
> > > > > - @param[in] SecondLevelPagingEntry The second level paging entry.
> > > > > + @param[in] SecondLevelPagingEntry The second level paging entry.
> > > > > + @param[in] Is5LevelPaging If it is the 5 level paging.
> > > > > **/
> > > > > VOID
> > > > > DumpSecondLevelPagingEntry (
> > > > > - IN VOID *SecondLevelPagingEntry
> > > > > + IN VOID *SecondLevelPagingEntry,
> > > > > + IN BOOLEAN Is5LevelPaging
> > > > > )
> > > > > {
> > > > > + UINTN Index5;
> > > > > UINTN Index4;
> > > > > UINTN Index3;
> > > > > UINTN Index2;
> > > > > UINTN Index1;
> > > > > + UINTN Lvl5IndexEnd;
> > > > > + VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl5PtEntry;
> > > > > VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl4PtEntry;
> > > > > VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl3PtEntry;
> > > > > VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl2PtEntry; @@ -386,38
> > > +467,53
> > > > @@
> > > > > DumpSecondLevelPagingEntry (
> > > > >
> > > > > DEBUG ((DEBUG_VERBOSE,"================\n"));
> > > > > DEBUG ((DEBUG_VERBOSE,"DMAR Second Level Page Table:\n"));
> > > > > + DEBUG ((DEBUG_VERBOSE,"SecondLevelPagingEntry Base - 0x%x,
> > > > > Is5LevelPaging - %d\n", SecondLevelPagingEntry, Is5LevelPaging));
> > > > >
> > > > > - DEBUG ((DEBUG_VERBOSE,"SecondLevelPagingEntry Base - 0x%x\n",
> > > > > SecondLevelPagingEntry));
> > > > > + Lvl5IndexEnd = Is5LevelPaging ?
> > > > > SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY) : 1;
> > > > > Lvl4PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> > > > > *)SecondLevelPagingEntry;
> > > > > - for (Index4 = 0; Index4 <
> > > > > SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY); Index4++) {
> > > > > - if (Lvl4PtEntry[Index4].Uint64 != 0) {
> > > > > - DEBUG ((DEBUG_VERBOSE," Lvl4Pt Entry(0x%03x) - 0x%016lx\n",
> > > Index4,
> > > > > Lvl4PtEntry[Index4].Uint64));
> > > > > - }
> > > > > - if (Lvl4PtEntry[Index4].Uint64 == 0) {
> > > > > - continue;
> > > > > - }
> > > > > - Lvl3PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> > > > > *)(UINTN)VTD_64BITS_ADDRESS(Lvl4PtEntry[Index4].Bits.AddressLo,
> > > > > Lvl4PtEntry[Index4].Bits.AddressHi);
> > > > > - for (Index3 = 0; Index3 <
> > > > > SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY); Index3++) {
> > > > > - if (Lvl3PtEntry[Index3].Uint64 != 0) {
> > > > > - DEBUG ((DEBUG_VERBOSE," Lvl3Pt Entry(0x%03x) - 0x%016lx\n",
> > > > > Index3, Lvl3PtEntry[Index3].Uint64));
> > > > > + Lvl5PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> > > > > *)SecondLevelPagingEntry;
> > > > > +
> > > > > + for (Index5 = 0; Index5 < Lvl5IndexEnd; Index5++) {
> > > > > + if (Is5LevelPaging) {
> > > > > + if (Lvl5PtEntry[Index5].Uint64 != 0) {
> > > > > + DEBUG ((DEBUG_VERBOSE," Lvl5Pt Entry(0x%03x) - 0x%016lx\n",
> > > > > Index5, Lvl5PtEntry[Index5].Uint64));
> > > > > }
> > > > > - if (Lvl3PtEntry[Index3].Uint64 == 0) {
> > > > > + if (Lvl5PtEntry[Index5].Uint64 == 0) {
> > > > > continue;
> > > > > }
> > > > > + Lvl4PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> > > > > *)(UINTN)VTD_64BITS_ADDRESS(Lvl5PtEntry[Index5].Bits.AddressLo,
> > > > > Lvl5PtEntry[Index5].Bits.AddressHi);
> > > > > + }
> > > > >
> > > > > - Lvl2PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> > > > > *)(UINTN)VTD_64BITS_ADDRESS(Lvl3PtEntry[Index3].Bits.AddressLo,
> > > > > Lvl3PtEntry[Index3].Bits.AddressHi);
> > > > > - for (Index2 = 0; Index2 <
> > > > > SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY); Index2++) {
> > > > > - if (Lvl2PtEntry[Index2].Uint64 != 0) {
> > > > > - DEBUG ((DEBUG_VERBOSE," Lvl2Pt Entry(0x%03x) -
> > 0x%016lx\n",
> > > > > Index2, Lvl2PtEntry[Index2].Uint64));
> > > > > + for (Index4 = 0; Index4 <
> > > > > SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY); Index4++) {
> > > > > + if (Lvl4PtEntry[Index4].Uint64 != 0) {
> > > > > + DEBUG ((DEBUG_VERBOSE," Lvl4Pt Entry(0x%03x) - 0x%016lx\n",
> > > > > Index4, Lvl4PtEntry[Index4].Uint64));
> > > > > + }
> > > > > + if (Lvl4PtEntry[Index4].Uint64 == 0) {
> > > > > + continue;
> > > > > + }
> > > > > + Lvl3PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> > > > > *)(UINTN)VTD_64BITS_ADDRESS(Lvl4PtEntry[Index4].Bits.AddressLo,
> > > > > Lvl4PtEntry[Index4].Bits.AddressHi);
> > > > > + for (Index3 = 0; Index3 <
> > > > > SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY); Index3++) {
> > > > > + if (Lvl3PtEntry[Index3].Uint64 != 0) {
> > > > > + DEBUG ((DEBUG_VERBOSE," Lvl3Pt Entry(0x%03x) -
> 0x%016lx\n",
> > > > > Index3, Lvl3PtEntry[Index3].Uint64));
> > > > > }
> > > > > - if (Lvl2PtEntry[Index2].Uint64 == 0) {
> > > > > + if (Lvl3PtEntry[Index3].Uint64 == 0) {
> > > > > continue;
> > > > > }
> > > > > - if (Lvl2PtEntry[Index2].Bits.PageSize == 0) {
> > > > > - Lvl1PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> > > > > *)(UINTN)VTD_64BITS_ADDRESS(Lvl2PtEntry[Index2].Bits.AddressLo,
> > > > > Lvl2PtEntry[Index2].Bits.AddressHi);
> > > > > - for (Index1 = 0; Index1 <
> > > > > SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY); Index1++) {
> > > > > - if (Lvl1PtEntry[Index1].Uint64 != 0) {
> > > > > - DEBUG ((DEBUG_VERBOSE," Lvl1Pt Entry(0x%03x) -
> > > > 0x%016lx\n",
> > > > > Index1, Lvl1PtEntry[Index1].Uint64));
> > > > > +
> > > > > + Lvl2PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> > > > > *)(UINTN)VTD_64BITS_ADDRESS(Lvl3PtEntry[Index3].Bits.AddressLo,
> > > > > Lvl3PtEntry[Index3].Bits.AddressHi);
> > > > > + for (Index2 = 0; Index2 <
> > > > > SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY); Index2++) {
> > > > > + if (Lvl2PtEntry[Index2].Uint64 != 0) {
> > > > > + DEBUG ((DEBUG_VERBOSE," Lvl2Pt Entry(0x%03x) -
> > 0x%016lx\n",
> > > > > Index2, Lvl2PtEntry[Index2].Uint64));
> > > > > + }
> > > > > + if (Lvl2PtEntry[Index2].Uint64 == 0) {
> > > > > + continue;
> > > > > + }
> > > > > + if (Lvl2PtEntry[Index2].Bits.PageSize == 0) {
> > > > > + Lvl1PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> > > > > *)(UINTN)VTD_64BITS_ADDRESS(Lvl2PtEntry[Index2].Bits.AddressLo,
> > > > > Lvl2PtEntry[Index2].Bits.AddressHi);
> > > > > + for (Index1 = 0; Index1 <
> > > > > SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY); Index1++) {
> > > > > + if (Lvl1PtEntry[Index1].Uint64 != 0) {
> > > > > + DEBUG ((DEBUG_VERBOSE," Lvl1Pt Entry(0x%03x) -
> > > > 0x%016lx\n",
> > > > > Index1, Lvl1PtEntry[Index1].Uint64));
> > > > > + }
> > > > > }
> > > > > }
> > > > > }
> > > > > @@ -510,6 +606,7 @@ PageAttributeToLength (
> > > > > @param[in] VtdIndex The index used to identify a VTd
> > engine.
> > > > > @param[in] SecondLevelPagingEntry The second level paging entry
> > in
> > > > > VTd table for the device.
> > > > > @param[in] Address The address to be checked.
> > > > > + @param[in] Is5LevelPaging If it is the 5 level paging.
> > > > > @param[out] PageAttributes The page attribute of the page
> > entry.
> > > > >
> > > > > @return The page entry.
> > > > > @@ -519,6 +616,7 @@ GetSecondLevelPageTableEntry (
> > > > > IN UINTN VtdIndex,
> > > > > IN VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry,
> > > > > IN PHYSICAL_ADDRESS Address,
> > > > > + IN BOOLEAN Is5LevelPaging,
> > > > > OUT PAGE_ATTRIBUTE *PageAttribute
> > > > > )
> > > > > {
> > > > > @@ -526,17 +624,38 @@ GetSecondLevelPageTableEntry (
> > > > > UINTN Index2;
> > > > > UINTN Index3;
> > > > > UINTN Index4;
> > > > > + UINTN Index5;
> > > > > UINT64 *L1PageTable;
> > > > > UINT64 *L2PageTable;
> > > > > UINT64 *L3PageTable;
> > > > > UINT64 *L4PageTable;
> > > > > + UINT64 *L5PageTable;
> > > > >
> > > > > + Index5 = ((UINTN)RShiftU64 (Address, 48)) &
> > > PAGING_VTD_INDEX_MASK;
> > > > > Index4 = ((UINTN)RShiftU64 (Address, 39)) &
> > > PAGING_VTD_INDEX_MASK;
> > > > > Index3 = ((UINTN)Address >> 30) & PAGING_VTD_INDEX_MASK;
> > > > > Index2 = ((UINTN)Address >> 21) & PAGING_VTD_INDEX_MASK;
> > > > > Index1 = ((UINTN)Address >> 12) & PAGING_VTD_INDEX_MASK;
> > > > >
> > > > > - L4PageTable = (UINT64 *)SecondLevelPagingEntry;
> > > > > + if (Is5LevelPaging) {
> > > > > + L5PageTable = (UINT64 *)SecondLevelPagingEntry;
> > > > > + if (L5PageTable[Index5] == 0) {
> > > > > + L5PageTable[Index5] = (UINT64)(UINTN)AllocateZeroPages (1);
> > > > > + if (L5PageTable[Index5] == 0) {
> > > > > + DEBUG ((DEBUG_ERROR,"!!!!!! ALLOCATE LVL5 PAGE FAIL
> > > > > (0x%x)!!!!!!\n", Index4));
> > > > > + ASSERT(FALSE);
> > > > > + *PageAttribute = PageNone;
> > > > > + return NULL;
> > > > > + }
> > > > > + FlushPageTableMemory (VtdIndex, (UINTN)L5PageTable[Index5],
> > > > > SIZE_4KB);
> > > > > + SetSecondLevelPagingEntryAttribute
> > > > > ((VTD_SECOND_LEVEL_PAGING_ENTRY *)&L5PageTable[Index5],
> > > > > EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);
> > > > > + FlushPageTableMemory (VtdIndex, (UINTN)&L5PageTable[Index5],
> > > > > sizeof(L5PageTable[Index5]));
> > > > > + }
> > > > > + L4PageTable = (UINT64 *)(UINTN)(L5PageTable[Index5] &
> > > > > PAGING_4K_ADDRESS_MASK_64);
> > > > > + } else {
> > > > > + L4PageTable = (UINT64 *)SecondLevelPagingEntry; }
> > > > > +
> > > > > if (L4PageTable[Index4] == 0) {
> > > > > L4PageTable[Index4] = (UINT64)(UINTN)AllocateZeroPages (1);
> > > > > if (L4PageTable[Index4] == 0) {
> > > > > @@ -785,7 +904,7 @@ SetSecondLevelPagingAttribute (
> > > > > }
> > > > >
> > > > > while (Length != 0) {
> > > > > - PageEntry = GetSecondLevelPageTableEntry (VtdIndex,
> > > > > SecondLevelPagingEntry, BaseAddress, &PageAttribute);
> > > > > + PageEntry = GetSecondLevelPageTableEntry (VtdIndex,
> > > > > SecondLevelPagingEntry, BaseAddress,
> > > > > mVtdUnitInformation[VtdIndex].Is5LevelPaging, &PageAttribute);
> > > > > if (PageEntry == NULL) {
> > > > > DEBUG ((DEBUG_ERROR, "PageEntry - NULL\n"));
> > > > > return RETURN_UNSUPPORTED;
> > > > > @@ -913,7 +1032,7 @@ SetAccessAttribute (
> > > > >
> > > > > if (ExtContextEntry != NULL) {
> > > > > if (ExtContextEntry->Bits.Present == 0) {
> > > > > - SecondLevelPagingEntry = CreateSecondLevelPagingEntry (VtdIndex,
> > > 0);
> > > > > + SecondLevelPagingEntry = CreateSecondLevelPagingEntry
> > > > > + (VtdIndex, 0,
> > > > > mVtdUnitInformation[VtdIndex].Is5LevelPaging);
> > > > > DEBUG ((DEBUG_VERBOSE,"SecondLevelPagingEntry - 0x%x (S%04x
> > > > > B%02x D%02x F%02x) New\n", SecondLevelPagingEntry, Segment,
> > > > > SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.Function));
> > > > > Pt = (UINT64)RShiftU64 ((UINT64)(UINTN)SecondLevelPagingEntry,
> > > > > 12);
> > > > >
> > > > > @@ -922,7 +1041,7 @@ SetAccessAttribute (
> > > > > ExtContextEntry->Bits.DomainIdentifier = DomainIdentifier;
> > > > > ExtContextEntry->Bits.Present = 1;
> > > > > FlushPageTableMemory (VtdIndex, (UINTN)ExtContextEntry,
> > > > > sizeof(*ExtContextEntry));
> > > > > - DumpDmarExtContextEntryTable
> > > > > (mVtdUnitInformation[VtdIndex].ExtRootEntryTable);
> > > > > + DumpDmarExtContextEntryTable
> > > > > (mVtdUnitInformation[VtdIndex].ExtRootEntryTable,
> > > > > mVtdUnitInformation[VtdIndex].Is5LevelPaging);
> > > > > mVtdUnitInformation[VtdIndex].HasDirtyContext = TRUE;
> > > > > } else {
> > > > > SecondLevelPagingEntry = (VOID
> > > > > *)(UINTN)VTD_64BITS_ADDRESS(ExtContextEntry-
> > > > > >Bits.SecondLevelPageTranslationPointerLo, ExtContextEntry-
> > > > > >Bits.SecondLevelPageTranslationPointerHi);
> > > > > @@ -930,7 +1049,7 @@ SetAccessAttribute (
> > > > > }
> > > > > } else if (ContextEntry != NULL) {
> > > > > if (ContextEntry->Bits.Present == 0) {
> > > > > - SecondLevelPagingEntry = CreateSecondLevelPagingEntry (VtdIndex,
> > > 0);
> > > > > + SecondLevelPagingEntry = CreateSecondLevelPagingEntry
> > > > > + (VtdIndex, 0,
> > > > > mVtdUnitInformation[VtdIndex].Is5LevelPaging);
> > > > > DEBUG ((DEBUG_VERBOSE,"SecondLevelPagingEntry - 0x%x (S%04x
> > > > > B%02x D%02x F%02x) New\n", SecondLevelPagingEntry, Segment,
> > > > > SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.Function));
> > > > > Pt = (UINT64)RShiftU64 ((UINT64)(UINTN)SecondLevelPagingEntry,
> > > > > 12);
> > > > >
> > > > > @@ -939,7 +1058,7 @@ SetAccessAttribute (
> > > > > ContextEntry->Bits.DomainIdentifier = DomainIdentifier;
> > > > > ContextEntry->Bits.Present = 1;
> > > > > FlushPageTableMemory (VtdIndex, (UINTN)ContextEntry,
> > > > > sizeof(*ContextEntry));
> > > > > - DumpDmarContextEntryTable
> > > > > (mVtdUnitInformation[VtdIndex].RootEntryTable);
> > > > > + DumpDmarContextEntryTable
> > > > > (mVtdUnitInformation[VtdIndex].RootEntryTable,
> > > > > mVtdUnitInformation[VtdIndex].Is5LevelPaging);
> > > > > mVtdUnitInformation[VtdIndex].HasDirtyContext = TRUE;
> > > > > } else {
> > > > > SecondLevelPagingEntry = (VOID
> > > > > *)(UINTN)VTD_64BITS_ADDRESS(ContextEntry-
> > > > > >Bits.SecondLevelPageTranslationPointerLo, ContextEntry-
> > > > > >Bits.SecondLevelPageTranslationPointerHi);
> > > > > @@ -1000,7 +1119,7 @@ AlwaysEnablePageAttribute (
> > > > >
> > > > > if (mVtdUnitInformation[VtdIndex].FixedSecondLevelPagingEntry == 0)
> > {
> > > > > DEBUG((DEBUG_INFO, "CreateSecondLevelPagingEntry - %d\n",
> > > > > VtdIndex));
> > > > > - mVtdUnitInformation[VtdIndex].FixedSecondLevelPagingEntry =
> > > > > CreateSecondLevelPagingEntry (VtdIndex,
> EDKII_IOMMU_ACCESS_READ
> > |
> > > > > EDKII_IOMMU_ACCESS_WRITE);
> > > > > + mVtdUnitInformation[VtdIndex].FixedSecondLevelPagingEntry =
> > > > > CreateSecondLevelPagingEntry (VtdIndex,
> EDKII_IOMMU_ACCESS_READ
> > |
> > > > > EDKII_IOMMU_ACCESS_WRITE,
> > > > > mVtdUnitInformation[VtdIndex].Is5LevelPaging);
> > > > > }
> > > > >
> > > > > SecondLevelPagingEntry =
> > > > > mVtdUnitInformation[VtdIndex].FixedSecondLevelPagingEntry;
> > > > > diff --git
> > > > >
> > >
> > a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTableEx.
> > > > > c
> > > > >
> > >
> > b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTableEx.
> > > > > c
> > > > > index 0ed9e3ca..3918eeee 100644
> > > > > ---
> > > > >
> > >
> > a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTableEx.
> > > > > c
> > > > > +++
> > > > >
> > >
> > b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTableEx.
> > > > > c
> > > > > @@ -78,11 +78,32 @@ CreateExtContextEntry (
> > > > >
> > > > > DEBUG ((DEBUG_INFO,"DOMAIN: S%04x, B%02x D%02x F%02x\n",
> > > > > mVtdUnitInformation[VtdIndex].Segment, SourceId.Bits.Bus,
> > > > > SourceId.Bits.Device, SourceId.Bits.Function));
> > > > >
> > > > > - if ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW & BIT2) == 0)
> > > {
> > > > > - DEBUG((DEBUG_ERROR, "!!!! 4-level page-table is not supported on
> > > > > VTD %d !!!!\n", VtdIndex));
> > > > > + mVtdUnitInformation[VtdIndex].Is5LevelPaging = FALSE;
> > > > > + if ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW & BIT3) != 0)
> > > {
> > > > > + if ((PcdGet8(PcdVTdPolicyPropertyMask) & BIT3) != 0) {
> > > > > + DEBUG((DEBUG_ERROR, "Force to use 4-level page-table on VTD
> > > > > + %d\n",
> > > > > VtdIndex));
> > > > > + ExtContextEntry->Bits.AddressWidth = 0x2;
> > > > > + } if ((PcdGet8(PcdVTdPolicyPropertyMask) & BIT4) != 0) {
> > > > > + DEBUG((DEBUG_ERROR, "Force to use 5-level page-table on VTD
> > > > > + %d\n",
> > > > > VtdIndex));
> > > > > + ExtContextEntry->Bits.AddressWidth = 0x3;
> > > > > + mVtdUnitInformation[VtdIndex].Is5LevelPaging = TRUE;
> > > > > + } else {
> > > > > + if (mAcpiDmarTable->HostAddressWidth > 48) {
> > > > > + DEBUG((DEBUG_ERROR, "Using 5-level page-table on
> VTD %d\n",
> > > > > VtdIndex));
> > > > > + ExtContextEntry->Bits.AddressWidth = 0x3;
> > > > > + mVtdUnitInformation[VtdIndex].Is5LevelPaging = TRUE;
> > > > > + } else {
> > > > > + DEBUG((DEBUG_ERROR, "Using 4-level page-table on
> VTD %d\n",
> > > > > VtdIndex));
> > > > > + ExtContextEntry->Bits.AddressWidth = 0x2;
> > > > > + }
> > > > > + }
> > > > > + } else if ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW &
> > > > > + BIT2) !=
> > > > > 0) {
> > > > > + DEBUG((DEBUG_ERROR, "Using 4-level page-table on VTD %d\n",
> > > > > VtdIndex));
> > > > > + ExtContextEntry->Bits.AddressWidth = 0x2;
> > > > > + } else {
> > > > > + DEBUG((DEBUG_ERROR, "!!!! Page-table type is not supported on
> > > > > VTD %d !!!!\n", VtdIndex));
> > > > > return EFI_UNSUPPORTED;
> > > > > }
> > > > > - ExtContextEntry->Bits.AddressWidth = 0x2;
> > > > > }
> > > > >
> > > > > FlushPageTableMemory (VtdIndex,
> > > > > (UINTN)mVtdUnitInformation[VtdIndex].ExtRootEntryTable,
> > > > > EFI_PAGES_TO_SIZE(EntryTablePages));
> > > > > @@ -93,11 +114,13 @@ CreateExtContextEntry (
> > > > > /**
> > > > > Dump DMAR extended context entry table.
> > > > >
> > > > > - @param[in] ExtRootEntry DMAR extended root entry.
> > > > > + @param[in] ExtRootEntry DMAR extended root entry.
> > > > > + @param[in] Is5LevelPaging If it is the 5 level paging.
> > > > > **/
> > > > > VOID
> > > > > DumpDmarExtContextEntryTable (
> > > > > - IN VTD_EXT_ROOT_ENTRY *ExtRootEntry
> > > > > + IN VTD_EXT_ROOT_ENTRY *ExtRootEntry, IN BOOLEAN
> > Is5LevelPaging
> > > > > )
> > > > > {
> > > > > UINTN Index;
> > > > > @@ -127,7 +150,7 @@ DumpDmarExtContextEntryTable (
> > > > > if (ExtContextEntry[Index2].Bits.Present == 0) {
> > > > > continue;
> > > > > }
> > > > > - DumpSecondLevelPagingEntry ((VOID
> > > > >
> > >
> > *)(UINTN)VTD_64BITS_ADDRESS(ExtContextEntry[Index2].Bits.SecondLevelPa
> > > > > geTranslationPointerLo,
> > > > > ExtContextEntry[Index2].Bits.SecondLevelPageTranslationPointerHi));
> > > > > + DumpSecondLevelPagingEntry ((VOID
> > > > >
> > >
> > *)(UINTN)VTD_64BITS_ADDRESS(ExtContextEntry[Index2].Bits.SecondLevelPa
> > > > > geTranslationPointerLo,
> > > > > ExtContextEntry[Index2].Bits.SecondLevelPageTranslationPointerHi),
> > > > > Is5LevelPaging);
> > > > > }
> > > > >
> > > > > if (ExtRootEntry[Index].Bits.UpperPresent == 0) { diff --git
> > > > > a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/VtdReg.c
> > > > > b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/VtdReg.c
> > > > > index 699639ba..686d235f 100644
> > > > > --- a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/VtdReg.c
> > > > > +++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/VtdReg.c
> > > > > @@ -174,8 +174,14 @@ PrepareVtdConfig (
> > > > > if ((mVtdUnitInformation[Index].CapReg.Bits.SLLPS & BIT0) == 0) {
> > > > > DEBUG((DEBUG_WARN, "!!!! 2MB super page is not supported on
> > > VTD
> > > > > %d !!!!\n", Index));
> > > > > }
> > > > > - if ((mVtdUnitInformation[Index].CapReg.Bits.SAGAW & BIT2) == 0) {
> > > > > - DEBUG((DEBUG_ERROR, "!!!! 4-level page-table is not supported on
> > > > > VTD %d !!!!\n", Index));
> > > > > + if ((mVtdUnitInformation[Index].CapReg.Bits.SAGAW & BIT3) != 0) {
> > > > > + DEBUG((DEBUG_INFO, "Support 5-level page-table on VTD %d\n",
> > > > > Index));
> > > > > + }
> > > > > + if ((mVtdUnitInformation[Index].CapReg.Bits.SAGAW & BIT2) != 0) {
> > > > > + DEBUG((DEBUG_INFO, "Support 4-level page-table on VTD %d\n",
> > > > > Index));
> > > > > + }
> > > > > + if ((mVtdUnitInformation[Index].CapReg.Bits.SAGAW & (BIT3 |
> > > > > + BIT2)) == 0)
> > > > > {
> > > > > + DEBUG((DEBUG_ERROR, "!!!! Page-table type 0x%X is not
> > supported
> > > > > + on
> > > > > VTD %d !!!!\n", Index,
> > mVtdUnitInformation[Index].CapReg.Bits.SAGAW));
> > > > > return ;
> > > > > }
> > > > >
> > > > > diff --git a/Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dec
> > > > > b/Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dec
> > > > > index 284820af..8f1edfe2 100644
> > > > > --- a/Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dec
> > > > > +++ b/Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dec
> > > > > @@ -95,6 +95,9 @@
> > > > > # BIT0: Enable IOMMU during boot (If DMAR table is installed in
> > > > > DXE. If VTD_INFO_PPI is installed in PEI.)
> > > > > # BIT1: Enable IOMMU when transfer control to OS (ExitBootService
> > > > > in normal boot. EndOfPEI in S3)
> > > > > # BIT2: Force no IOMMU access attribute request recording before
> > > > > DMAR table is installed.
> > > > > + # BIT3: Force to use 4 level paging.
> > > > > + # BIT4: If iommu support 5 level paging, force to use 5 level paging.
> > > > > + # (If both BIT3 and BIT4 are set, force to use 4 level paging.)
> > > > > # @Prompt The policy for VTd driver behavior.
> > > > >
> > > > >
> > >
> > gIntelSiliconPkgTokenSpaceGuid.PcdVTdPolicyPropertyMask|1|UINT8|0x000
> > > > > 00002
> > > > >
> > > > > --
> > > > > 2.16.2.windows.1
> >
> >
> >
> >
> >
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2020-11-23 8:10 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2020-11-18 1:17 [PATCH v3] IntelSiliconPkg/VTd: Add iommu 5 level paging support Sheng Wei
2020-11-18 1:39 ` Yao, Jiewen
2020-11-18 2:33 ` Sheng Wei
2020-11-18 2:49 ` Yao, Jiewen
[not found] ` <16487A52A9CBAF90.960@groups.io>
2020-11-18 3:03 ` [edk2-devel] " Yao, Jiewen
2020-11-23 8:10 ` Sheng Wei
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox