public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [PATCH v4] IntelSiliconPkg/VTd: Add iommu 5 level paging support
@ 2020-11-23  8:03 Sheng Wei
  2020-11-23  8:43 ` Yao, Jiewen
  0 siblings, 1 reply; 3+ messages in thread
From: Sheng Wei @ 2020-11-23  8:03 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     | 281 +++++++++++++++------
 .../Feature/VTd/IntelVTdDxe/TranslationTableEx.c   |  31 ++-
 .../Feature/VTd/IntelVTdDxe/VtdReg.c               |  10 +-
 5 files changed, 245 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..6c786b40 100644
--- a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTable.c
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTable.c
@@ -128,11 +128,26 @@ 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) {
+      mVtdUnitInformation[VtdIndex].Is5LevelPaging = TRUE;
+      if (mAcpiDmarTable->HostAddressWidth <= 48) {
+        if ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW & BIT2) != 0) {
+          mVtdUnitInformation[VtdIndex].Is5LevelPaging = FALSE;
+        }
+      }
+    } else if ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW & BIT2) == 0) {
+      DEBUG((DEBUG_ERROR, "!!!! Page-table type is not supported on VTD %d !!!!\n", VtdIndex));
       return EFI_UNSUPPORTED;
     }
-    ContextEntry->Bits.AddressWidth = 0x2;
+
+    if (mVtdUnitInformation[VtdIndex].Is5LevelPaging) {
+      ContextEntry->Bits.AddressWidth = 0x3;
+      DEBUG((DEBUG_ERROR, "Using 4-level page-table on VTD %d\n", VtdIndex));
+    } else {
+      ContextEntry->Bits.AddressWidth = 0x2;
+      DEBUG((DEBUG_ERROR, "Using 5-level page-table on VTD %d\n", VtdIndex));
+    }
   }
 
   FlushPageTableMemory (VtdIndex, (UINTN)mVtdUnitInformation[VtdIndex].RootEntryTable, EFI_PAGES_TO_SIZE(EntryTablePages));
@@ -148,6 +163,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 +173,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 +207,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 +220,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);
+      }
+
+      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));
 
-      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;
+      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 +332,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 +394,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 +429,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 +438,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 +461,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 +600,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 +610,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 +618,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 +898,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 +1026,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 +1035,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 +1043,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 +1052,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 +1113,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..a4466891 100644
--- a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTableEx.c
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTableEx.c
@@ -78,11 +78,28 @@ 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) {
+      mVtdUnitInformation[VtdIndex].Is5LevelPaging = TRUE;
+      if (mAcpiDmarTable->HostAddressWidth <= 48) {
+        if ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW & BIT2) != 0) {
+          mVtdUnitInformation[VtdIndex].Is5LevelPaging = FALSE;
+        }
+      }
+    } else if ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW & BIT2) == 0) {
+      DEBUG((DEBUG_ERROR, "!!!! Page-table type is not supported on VTD %d !!!!\n", VtdIndex));
       return EFI_UNSUPPORTED;
     }
-    ExtContextEntry->Bits.AddressWidth = 0x2;
+
+    if (mVtdUnitInformation[VtdIndex].Is5LevelPaging) {
+      ExtContextEntry->Bits.AddressWidth = 0x3;
+      DEBUG((DEBUG_ERROR, "Using 4-level page-table on VTD %d\n", VtdIndex));
+    } else {
+      ExtContextEntry->Bits.AddressWidth = 0x2;
+      DEBUG((DEBUG_ERROR, "Using 5-level page-table on VTD %d\n", VtdIndex));
+    }
+
+
   }
 
   FlushPageTableMemory (VtdIndex, (UINTN)mVtdUnitInformation[VtdIndex].ExtRootEntryTable, EFI_PAGES_TO_SIZE(EntryTablePages));
@@ -93,11 +110,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 +146,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 ;
     }
 
-- 
2.16.2.windows.1


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH v4] IntelSiliconPkg/VTd: Add iommu 5 level paging support
  2020-11-23  8:03 [PATCH v4] IntelSiliconPkg/VTd: Add iommu 5 level paging support Sheng Wei
@ 2020-11-23  8:43 ` Yao, Jiewen
  2020-11-24  5:43   ` Sheng Wei
  0 siblings, 1 reply; 3+ messages in thread
From: Yao, Jiewen @ 2020-11-23  8:43 UTC (permalink / raw)
  To: Sheng, W, devel@edk2.groups.io
  Cc: Ni, Ray, Chaganty, Rangasai V, Huang, Jenny

Thanks.

I only reviewed the policy part. Comment below:

1) I recommend you can merge below 2 if into one - if ((mAcpiDmarTable->HostAddressWidth <= 48) && (mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW & BIT2) != 0)) {
You can use 2 lines, but there is no need to use 2 if.

+      if (mAcpiDmarTable->HostAddressWidth <= 48) {
+        if ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW & BIT2) != 0) {
+          mVtdUnitInformation[VtdIndex].Is5LevelPaging = FALSE;
+        }
+      }

2) I think below code has typo.
The DEBUG message about 4-level and 5-level should be reversed.
Also we should use DEBUG_INFO instead of DEBUG_ERROR.

+    if (mVtdUnitInformation[VtdIndex].Is5LevelPaging) {
+      ContextEntry->Bits.AddressWidth = 0x3;
+      DEBUG((DEBUG_ERROR, "Using 4-level page-table on VTD %d\n", VtdIndex));
+    } else {
+      ContextEntry->Bits.AddressWidth = 0x2;
+      DEBUG((DEBUG_ERROR, "Using 5-level page-table on VTD %d\n", VtdIndex));
+    }




> -----Original Message-----
> From: Sheng, W <w.sheng@intel.com>
> Sent: Monday, November 23, 2020 4:04 PM
> 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 v4] 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     | 281 +++++++++++++++--
> ----
>  .../Feature/VTd/IntelVTdDxe/TranslationTableEx.c   |  31 ++-
>  .../Feature/VTd/IntelVTdDxe/VtdReg.c               |  10 +-
>  5 files changed, 245 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..6c786b40 100644
> ---
> a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTable.c
> +++
> b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTable.c
> @@ -128,11 +128,26 @@ 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) {
> +      mVtdUnitInformation[VtdIndex].Is5LevelPaging = TRUE;
> +      if (mAcpiDmarTable->HostAddressWidth <= 48) {
> +        if ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW & BIT2) != 0) {
> +          mVtdUnitInformation[VtdIndex].Is5LevelPaging = FALSE;
> +        }
> +      }
> +    } else if ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW & BIT2) ==
> 0) {
> +      DEBUG((DEBUG_ERROR, "!!!! Page-table type is not supported on
> VTD %d !!!!\n", VtdIndex));
>        return EFI_UNSUPPORTED;
>      }
> -    ContextEntry->Bits.AddressWidth = 0x2;
> +
> +    if (mVtdUnitInformation[VtdIndex].Is5LevelPaging) {
> +      ContextEntry->Bits.AddressWidth = 0x3;
> +      DEBUG((DEBUG_ERROR, "Using 4-level page-table on VTD %d\n",
> VtdIndex));
> +    } else {
> +      ContextEntry->Bits.AddressWidth = 0x2;
> +      DEBUG((DEBUG_ERROR, "Using 5-level page-table on VTD %d\n",
> VtdIndex));
> +    }
>    }
> 
>    FlushPageTableMemory (VtdIndex,
> (UINTN)mVtdUnitInformation[VtdIndex].RootEntryTable,
> EFI_PAGES_TO_SIZE(EntryTablePages));
> @@ -148,6 +163,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 +173,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 +207,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 +220,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);
> +      }
> +
> +      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));
> 
> -      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;
> +      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 +332,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 +394,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 +429,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 +438,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 +461,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 +600,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 +610,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 +618,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 +898,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 +1026,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 +1035,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 +1043,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 +1052,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 +1113,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..a4466891 100644
> ---
> a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTableEx.
> c
> +++
> b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTableEx.
> c
> @@ -78,11 +78,28 @@ 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) {
> +      mVtdUnitInformation[VtdIndex].Is5LevelPaging = TRUE;
> +      if (mAcpiDmarTable->HostAddressWidth <= 48) {
> +        if ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW & BIT2) != 0) {
> +          mVtdUnitInformation[VtdIndex].Is5LevelPaging = FALSE;
> +        }
> +      }
> +    } else if ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW & BIT2) ==
> 0) {
> +      DEBUG((DEBUG_ERROR, "!!!! Page-table type is not supported on
> VTD %d !!!!\n", VtdIndex));
>        return EFI_UNSUPPORTED;
>      }
> -    ExtContextEntry->Bits.AddressWidth = 0x2;
> +
> +    if (mVtdUnitInformation[VtdIndex].Is5LevelPaging) {
> +      ExtContextEntry->Bits.AddressWidth = 0x3;
> +      DEBUG((DEBUG_ERROR, "Using 4-level page-table on VTD %d\n",
> VtdIndex));
> +    } else {
> +      ExtContextEntry->Bits.AddressWidth = 0x2;
> +      DEBUG((DEBUG_ERROR, "Using 5-level page-table on VTD %d\n",
> VtdIndex));
> +    }
> +
> +
>    }
> 
>    FlushPageTableMemory (VtdIndex,
> (UINTN)mVtdUnitInformation[VtdIndex].ExtRootEntryTable,
> EFI_PAGES_TO_SIZE(EntryTablePages));
> @@ -93,11 +110,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 +146,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 ;
>      }
> 
> --
> 2.16.2.windows.1


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH v4] IntelSiliconPkg/VTd: Add iommu 5 level paging support
  2020-11-23  8:43 ` Yao, Jiewen
@ 2020-11-24  5:43   ` Sheng Wei
  0 siblings, 0 replies; 3+ messages in thread
From: Sheng Wei @ 2020-11-24  5:43 UTC (permalink / raw)
  To: Yao, Jiewen, devel@edk2.groups.io
  Cc: Ni, Ray, Chaganty, Rangasai V, Huang, Jenny

Hi Jiewen, All,
Thank you for the review. I just check and update the patch.
https://edk2.groups.io/g/devel/message/67865?p=,,,20,0,0,0::relevance,,posterid%3A2558558,20,2,0,78471874
Could we continue the patch review ?
BR
Sheng Wei

> -----Original Message-----
> From: Yao, Jiewen <jiewen.yao@intel.com>
> Sent: 2020年11月23日 16:44
> 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 v4] IntelSiliconPkg/VTd: Add iommu 5 level paging support
> 
> Thanks.
> 
> I only reviewed the policy part. Comment below:
> 
> 1) I recommend you can merge below 2 if into one - if ((mAcpiDmarTable-
> >HostAddressWidth <= 48) &&
> (mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW & BIT2) != 0)) { You can
> use 2 lines, but there is no need to use 2 if.
> 
> +      if (mAcpiDmarTable->HostAddressWidth <= 48) {
> +        if ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW & BIT2) != 0) {
> +          mVtdUnitInformation[VtdIndex].Is5LevelPaging = FALSE;
> +        }
> +      }
> 
> 2) I think below code has typo.
> The DEBUG message about 4-level and 5-level should be reversed.
> Also we should use DEBUG_INFO instead of DEBUG_ERROR.
> 
> +    if (mVtdUnitInformation[VtdIndex].Is5LevelPaging) {
> +      ContextEntry->Bits.AddressWidth = 0x3;
> +      DEBUG((DEBUG_ERROR, "Using 4-level page-table on VTD %d\n",
> VtdIndex));
> +    } else {
> +      ContextEntry->Bits.AddressWidth = 0x2;
> +      DEBUG((DEBUG_ERROR, "Using 5-level page-table on VTD %d\n",
> VtdIndex));
> +    }
> 
> 
> 
> 
> > -----Original Message-----
> > From: Sheng, W <w.sheng@intel.com>
> > Sent: Monday, November 23, 2020 4:04 PM
> > 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 v4] 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     | 281 +++++++++++++++--
> > ----
> >  .../Feature/VTd/IntelVTdDxe/TranslationTableEx.c   |  31 ++-
> >  .../Feature/VTd/IntelVTdDxe/VtdReg.c               |  10 +-
> >  5 files changed, 245 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..6c786b40 100644
> > ---
> > a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTab
> > le.c
> > +++
> > b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTab
> > le.c @@ -128,11 +128,26 @@ 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) {
> > +      mVtdUnitInformation[VtdIndex].Is5LevelPaging = TRUE;
> > +      if (mAcpiDmarTable->HostAddressWidth <= 48) {
> > +        if ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW & BIT2) != 0) {
> > +          mVtdUnitInformation[VtdIndex].Is5LevelPaging = FALSE;
> > +        }
> > +      }
> > +    } else if ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW &
> > + BIT2) ==
> > 0) {
> > +      DEBUG((DEBUG_ERROR, "!!!! Page-table type is not supported on
> > VTD %d !!!!\n", VtdIndex));
> >        return EFI_UNSUPPORTED;
> >      }
> > -    ContextEntry->Bits.AddressWidth = 0x2;
> > +
> > +    if (mVtdUnitInformation[VtdIndex].Is5LevelPaging) {
> > +      ContextEntry->Bits.AddressWidth = 0x3;
> > +      DEBUG((DEBUG_ERROR, "Using 4-level page-table on VTD %d\n",
> > VtdIndex));
> > +    } else {
> > +      ContextEntry->Bits.AddressWidth = 0x2;
> > +      DEBUG((DEBUG_ERROR, "Using 5-level page-table on VTD %d\n",
> > VtdIndex));
> > +    }
> >    }
> >
> >    FlushPageTableMemory (VtdIndex,
> > (UINTN)mVtdUnitInformation[VtdIndex].RootEntryTable,
> > EFI_PAGES_TO_SIZE(EntryTablePages));
> > @@ -148,6 +163,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 +173,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 +207,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 +220,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);
> > +      }
> > +
> > +      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));
> >
> > -      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;
> > +      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 +332,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 +394,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 +429,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 +438,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 +461,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 +600,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 +610,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 +618,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 +898,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 +1026,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 +1035,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 +1043,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 +1052,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 +1113,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..a4466891 100644
> > ---
> > a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTableEx.
> > c
> > +++
> > b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTableEx.
> > c
> > @@ -78,11 +78,28 @@ 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) {
> > +      mVtdUnitInformation[VtdIndex].Is5LevelPaging = TRUE;
> > +      if (mAcpiDmarTable->HostAddressWidth <= 48) {
> > +        if ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW & BIT2) != 0) {
> > +          mVtdUnitInformation[VtdIndex].Is5LevelPaging = FALSE;
> > +        }
> > +      }
> > +    } else if ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW &
> > + BIT2) ==
> > 0) {
> > +      DEBUG((DEBUG_ERROR, "!!!! Page-table type is not supported on
> > VTD %d !!!!\n", VtdIndex));
> >        return EFI_UNSUPPORTED;
> >      }
> > -    ExtContextEntry->Bits.AddressWidth = 0x2;
> > +
> > +    if (mVtdUnitInformation[VtdIndex].Is5LevelPaging) {
> > +      ExtContextEntry->Bits.AddressWidth = 0x3;
> > +      DEBUG((DEBUG_ERROR, "Using 4-level page-table on VTD %d\n",
> > VtdIndex));
> > +    } else {
> > +      ExtContextEntry->Bits.AddressWidth = 0x2;
> > +      DEBUG((DEBUG_ERROR, "Using 5-level page-table on VTD %d\n",
> > VtdIndex));
> > +    }
> > +
> > +
> >    }
> >
> >    FlushPageTableMemory (VtdIndex,
> > (UINTN)mVtdUnitInformation[VtdIndex].ExtRootEntryTable,
> > EFI_PAGES_TO_SIZE(EntryTablePages));
> > @@ -93,11 +110,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 +146,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 ;
> >      }
> >
> > --
> > 2.16.2.windows.1


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2020-11-24  5:43 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2020-11-23  8:03 [PATCH v4] IntelSiliconPkg/VTd: Add iommu 5 level paging support Sheng Wei
2020-11-23  8:43 ` Yao, Jiewen
2020-11-24  5:43   ` Sheng Wei

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox