[edk2-devel] [PATCH v3] IntelSiliconPkg/VTd: Add iommu 5 level paging support

Yao, Jiewen jiewen.yao at intel.com
Wed Nov 18 02:49:17 UTC 2020


Sorry I did not say clearly.

1) I mean the (SAGAW & BIT2) check should also happen inside of (SAGAW & BIT3), the first if.

Otherwise, the logic is:

If (5 level support) {
  If (need 4 level) {
    Do 4 level
  }
}

That is odd.

2) In general, I recommend we have a better way to manage test/debug code into production. The PCD should be used when it is absolutely necessary.
I think the policy should be as simple as possible. Otherwise, the production team wont know how to choose.


> -----Original Message-----
> From: Sheng, W <w.sheng at intel.com>
> Sent: Wednesday, November 18, 2020 10:33 AM
> To: Yao, Jiewen <jiewen.yao at intel.com>; devel at edk2.groups.io
> Cc: Ni, Ray <ray.ni at intel.com>; Chaganty, Rangasai V
> <rangasai.v.chaganty at intel.com>; Huang, Jenny <jenny.huang at intel.com>
> Subject: RE: [PATCH v3] IntelSiliconPkg/VTd: Add iommu 5 level paging
> support
> 
> Hi Jeiwen,
> For comment 1:
> The code about (SAGAW & BIT2) is just behand (SAGAW & BIT3)
> 
> > > +          DEBUG((DEBUG_ERROR, "Using 4-level page-table on VTD %d\n",
> > > VtdIndex));
> > > +          ExtContextEntry->Bits.AddressWidth = 0x2;
> > > +        }
> > > +      }
> > > +    } else if ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW &
> > > + BIT2) !=
> > > 0) {
> > > +      DEBUG((DEBUG_ERROR, "Using 4-level page-table on VTD %d\n",
> > > VtdIndex));
> > > +      ExtContextEntry->Bits.AddressWidth = 0x2;
> > > +    } else {
> > > +      DEBUG((DEBUG_ERROR, "!!!! Page-table type is not supported on
> > > VTD %d !!!!\n", VtdIndex));
> > >        return EFI_UNSUPPORTED;
> > >      }
> > > -    ExtContextEntry->Bits.AddressWidth = 0x2;
> > >    }
> 
> For comment 2:
> >   #  BIT3: Force to use 4 level paging.
> >   #  BIT4: If iommu support 5 level paging, force to use 5 level paging.
> >   #    (If both BIT3 and BIT4 are set, force to use 4 level paging.)
> Mostly, these 2 bits are for debug/test purpose, it could be used to force the
> page table depth.
> Do you think it is no necessary? Or we could find another solution ?
> 
> Thank you
> BR
> Sheng Wei
> 
> 
> > -----Original Message-----
> > From: Yao, Jiewen <jiewen.yao at intel.com>
> > Sent: 2020年11月18日 9:39
> > To: Sheng, W <w.sheng at intel.com>; devel at edk2.groups.io
> > Cc: Ni, Ray <ray.ni at intel.com>; Chaganty, Rangasai V
> > <rangasai.v.chaganty at intel.com>; Huang, Jenny <jenny.huang at intel.com>
> > Subject: RE: [PATCH v3] IntelSiliconPkg/VTd: Add iommu 5 level paging
> support
> >
> > Hi
> > I have 2 comments:
> >
> > 1) below capability check seems not correct.
> >
> > (SAGAW & BIT3) is for 5 level only.
> > We need check (SAGAW & BIT2) for 4 level. But I do not see the code. Do I
> miss
> > something?
> >
> >     if ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW & BIT3) != 0) {
> >       if ((PcdGet8(PcdVTdPolicyPropertyMask) & BIT3) != 0) {
> >         DEBUG((DEBUG_ERROR, "Force to use 4-level page-table on
> VTD %d\n",
> > VtdIndex));
> >         ContextEntry->Bits.AddressWidth = 0x2;
> >       } if ((PcdGet8(PcdVTdPolicyPropertyMask) & BIT4) != 0) {
> >         DEBUG((DEBUG_ERROR, "Force to use 5-level page-table on
> VTD %d\n",
> > VtdIndex));
> >         ContextEntry->Bits.AddressWidth = 0x3;
> >         mVtdUnitInformation[VtdIndex].Is5LevelPaging = TRUE;
> >       } else {
> >         if (mAcpiDmarTable->HostAddressWidth > 48) {
> >           DEBUG((DEBUG_ERROR, "Using 5-level page-table on VTD %d\n",
> > VtdIndex));
> >           ContextEntry->Bits.AddressWidth = 0x3;
> >           mVtdUnitInformation[VtdIndex].Is5LevelPaging = TRUE;
> >         } else {
> >           DEBUG((DEBUG_ERROR, "Using 4-level page-table on VTD %d\n",
> > VtdIndex));
> >           ContextEntry->Bits.AddressWidth = 0x2;
> >         }
> >       }
> >
> > 2) I am wondering, do we really need 2 bit for level selection ?
> > What if force 4 level, but the platform does not support?
> > What if force 5 level, but the platform does not support?
> >
> >   #  BIT3: Force to use 4 level paging.
> >   #  BIT4: If iommu support 5 level paging, force to use 5 level paging.
> >   #    (If both BIT3 and BIT4 are set, force to use 4 level paging.)
> >
> >
> gIntelSiliconPkgTokenSpaceGuid.PcdVTdPolicyPropertyMask|1|UINT8|0x000
> 00
> > 002
> >
> > Can we align the solution in DXE/SMM paging solution?
> >
> >
> >
> > > -----Original Message-----
> > > From: Sheng, W <w.sheng at intel.com>
> > > Sent: Wednesday, November 18, 2020 9:18 AM
> > > To: devel at edk2.groups.io
> > > Cc: Ni, Ray <ray.ni at intel.com>; Chaganty, Rangasai V
> > > <rangasai.v.chaganty at intel.com>; Yao, Jiewen <jiewen.yao at intel.com>;
> > > Huang, Jenny <jenny.huang at intel.com>
> > > Subject: [PATCH v3] IntelSiliconPkg/VTd: Add iommu 5 level paging
> > > support
> > >
> > > Support iommu 5 level paging for translation table.
> > >
> > > REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3067
> > >
> > > Signed-off-by: Sheng Wei <w.sheng at intel.com>
> > > Cc: Ray Ni <ray.ni at intel.com>
> > > Cc: Rangasai V Chaganty <rangasai.v.chaganty at intel.com>
> > > Cc: Jiewen Yao <jiewen.yao at intel.com>
> > > Cc: Jenny Huang <jenny.huang at intel.com>
> > > ---
> > >  .../Feature/VTd/IntelVTdDxe/DmaProtection.c        |   4 +-
> > >  .../Feature/VTd/IntelVTdDxe/DmaProtection.h        |  19 +-
> > >  .../Feature/VTd/IntelVTdDxe/TranslationTable.c     | 287
> +++++++++++++++--
> > > ----
> > >  .../Feature/VTd/IntelVTdDxe/TranslationTableEx.c   |  35 ++-
> > >  .../Feature/VTd/IntelVTdDxe/VtdReg.c               |  10 +-
> > >  Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dec  |   3 +
> > >  6 files changed, 258 insertions(+), 100 deletions(-)
> > >
> > > diff --git
> > > a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.
> > > c
> > > b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.
> > > c
> > > index 9b6135ef..628565ee 100644
> > > ---
> > > a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.
> > > c
> > > +++
> > > b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.
> > > c
> > > @@ -523,10 +523,10 @@ SetupVtd (
> > >    for (Index = 0; Index < mVtdUnitNumber; Index++) {
> > >      DEBUG ((DEBUG_INFO,"VTD Unit %d (Segment: %04x)\n", Index,
> > > mVtdUnitInformation[Index].Segment));
> > >      if (mVtdUnitInformation[Index].ExtRootEntryTable != NULL) {
> > > -      DumpDmarExtContextEntryTable
> > > (mVtdUnitInformation[Index].ExtRootEntryTable);
> > > +      DumpDmarExtContextEntryTable
> > > (mVtdUnitInformation[Index].ExtRootEntryTable,
> > > mVtdUnitInformation[Index].Is5LevelPaging);
> > >      }
> > >      if (mVtdUnitInformation[Index].RootEntryTable != NULL) {
> > > -      DumpDmarContextEntryTable
> > > (mVtdUnitInformation[Index].RootEntryTable);
> > > +      DumpDmarContextEntryTable
> > > (mVtdUnitInformation[Index].RootEntryTable,
> > > mVtdUnitInformation[Index].Is5LevelPaging);
> > >      }
> > >    }
> > >
> > > diff --git
> > > a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.
> > > h
> > > b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.
> > > h
> > > index a3331db8..f641cea0 100644
> > > ---
> > > a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.
> > > h
> > > +++
> > > b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.
> > > h
> > > @@ -77,6 +77,7 @@ typedef struct {
> > >    BOOLEAN                          HasDirtyContext;
> > >    BOOLEAN                          HasDirtyPages;
> > >    PCI_DEVICE_INFORMATION           PciDeviceInfo;
> > > +  BOOLEAN                          Is5LevelPaging;
> > >  } VTD_UNIT_INFORMATION;
> > >
> > >  //
> > > @@ -375,31 +376,37 @@ ParseDmarAcpiTableRmrr (
> > >  /**
> > >    Dump DMAR context entry table.
> > >
> > > -  @param[in]  RootEntry DMAR root entry.
> > > +  @param[in]  RootEntry       DMAR root entry.
> > > +  @param[in]  Is5LevelPaging  If it is the 5 level paging.
> > >  **/
> > >  VOID
> > >  DumpDmarContextEntryTable (
> > > -  IN VTD_ROOT_ENTRY *RootEntry
> > > +  IN VTD_ROOT_ENTRY *RootEntry,
> > > +  IN BOOLEAN Is5LevelPaging
> > >    );
> > >
> > >  /**
> > >    Dump DMAR extended context entry table.
> > >
> > > -  @param[in]  ExtRootEntry DMAR extended root entry.
> > > +  @param[in]  ExtRootEntry    DMAR extended root entry.
> > > +  @param[in]  Is5LevelPaging  If it is the 5 level paging.
> > >  **/
> > >  VOID
> > >  DumpDmarExtContextEntryTable (
> > > -  IN VTD_EXT_ROOT_ENTRY *ExtRootEntry
> > > +  IN VTD_EXT_ROOT_ENTRY *ExtRootEntry,  IN BOOLEAN Is5LevelPaging
> > >    );
> > >
> > >  /**
> > >    Dump DMAR second level paging entry.
> > >
> > > -  @param[in]  SecondLevelPagingEntry The second level paging entry.
> > > +  @param[in]  SecondLevelPagingEntry  The second level paging entry.
> > > +  @param[in]  Is5LevelPaging          If it is the 5 level paging.
> > >  **/
> > >  VOID
> > >  DumpSecondLevelPagingEntry (
> > > -  IN VOID *SecondLevelPagingEntry
> > > +  IN VOID *SecondLevelPagingEntry,
> > > +  IN BOOLEAN Is5LevelPaging
> > >    );
> > >
> > >  /**
> > > diff --git
> > > a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTab
> > > le.c
> > > b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTab
> > > le.c
> > > index 201d663d..cb59860a 100644
> > > ---
> > > a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTab
> > > le.c
> > > +++
> > > b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTab
> > > le.c @@ -128,11 +128,32 @@ CreateContextEntry (
> > >
> > >      DEBUG ((DEBUG_INFO,"Source: S%04x B%02x D%02x F%02x\n",
> > > mVtdUnitInformation[VtdIndex].Segment, SourceId.Bits.Bus,
> > > SourceId.Bits.Device, SourceId.Bits.Function));
> > >
> > > -    if ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW & BIT2) == 0)
> {
> > > -      DEBUG((DEBUG_ERROR, "!!!! 4-level page-table is not supported on
> > > VTD %d !!!!\n", VtdIndex));
> > > +    mVtdUnitInformation[VtdIndex].Is5LevelPaging = FALSE;
> > > +    if ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW & BIT3) != 0)
> {
> > > +      if ((PcdGet8(PcdVTdPolicyPropertyMask) & BIT3) != 0) {
> > > +        DEBUG((DEBUG_ERROR, "Force to use 4-level page-table on VTD
> > > + %d\n",
> > > VtdIndex));
> > > +        ContextEntry->Bits.AddressWidth = 0x2;
> > > +      } if ((PcdGet8(PcdVTdPolicyPropertyMask) & BIT4) != 0) {
> > > +        DEBUG((DEBUG_ERROR, "Force to use 5-level page-table on VTD
> > > + %d\n",
> > > VtdIndex));
> > > +        ContextEntry->Bits.AddressWidth = 0x3;
> > > +        mVtdUnitInformation[VtdIndex].Is5LevelPaging = TRUE;
> > > +      } else {
> > > +        if (mAcpiDmarTable->HostAddressWidth > 48) {
> > > +          DEBUG((DEBUG_ERROR, "Using 5-level page-table on VTD %d\n",
> > > VtdIndex));
> > > +          ContextEntry->Bits.AddressWidth = 0x3;
> > > +          mVtdUnitInformation[VtdIndex].Is5LevelPaging = TRUE;
> > > +        } else {
> > > +          DEBUG((DEBUG_ERROR, "Using 4-level page-table on VTD %d\n",
> > > VtdIndex));
> > > +          ContextEntry->Bits.AddressWidth = 0x2;
> > > +        }
> > > +      }
> > > +    } else if ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW &
> > > + BIT2) !=
> > > 0) {
> > > +      DEBUG((DEBUG_ERROR, "Using 4-level page-table on VTD %d\n",
> > > VtdIndex));
> > > +      ContextEntry->Bits.AddressWidth = 0x2;
> > > +    } else {
> > > +      DEBUG((DEBUG_ERROR, "!!!! Page-table type is not supported on
> > > VTD %d !!!!\n", VtdIndex));
> > >        return EFI_UNSUPPORTED;
> > >      }
> > > -    ContextEntry->Bits.AddressWidth = 0x2;
> > >    }
> > >
> > >    FlushPageTableMemory (VtdIndex,
> > > (UINTN)mVtdUnitInformation[VtdIndex].RootEntryTable,
> > > EFI_PAGES_TO_SIZE(EntryTablePages));
> > > @@ -148,6 +169,7 @@ CreateContextEntry (
> > >    @param[in]  MemoryBase                  The base of the memory.
> > >    @param[in]  MemoryLimit                 The limit of the memory.
> > >    @param[in]  IoMmuAccess                 The IOMMU access.
> > > +  @param[in]  Is5LevelPaging              If it is the 5 level paging.
> > >
> > >    @return The second level paging entry.
> > >  **/
> > > @@ -157,16 +179,23 @@ CreateSecondLevelPagingEntryTable (
> > >    IN VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry,
> > >    IN UINT64                        MemoryBase,
> > >    IN UINT64                        MemoryLimit,
> > > -  IN UINT64                        IoMmuAccess
> > > +  IN UINT64                        IoMmuAccess,
> > > +  IN BOOLEAN                       Is5LevelPaging
> > >    )
> > >  {
> > > +  UINTN                          Index5;
> > >    UINTN                          Index4;
> > >    UINTN                          Index3;
> > >    UINTN                          Index2;
> > > +  UINTN                          Lvl5Start;
> > > +  UINTN                          Lvl5End;
> > > +  UINTN                          Lvl4PagesStart;
> > > +  UINTN                          Lvl4PagesEnd;
> > >    UINTN                          Lvl4Start;
> > >    UINTN                          Lvl4End;
> > >    UINTN                          Lvl3Start;
> > >    UINTN                          Lvl3End;
> > > +  VTD_SECOND_LEVEL_PAGING_ENTRY  *Lvl5PtEntry;
> > >    VTD_SECOND_LEVEL_PAGING_ENTRY  *Lvl4PtEntry;
> > >    VTD_SECOND_LEVEL_PAGING_ENTRY  *Lvl3PtEntry;
> > >    VTD_SECOND_LEVEL_PAGING_ENTRY  *Lvl2PtEntry; @@ -184,7 +213,7
> > @@
> > > CreateSecondLevelPagingEntryTable (
> > >    if (SecondLevelPagingEntry == NULL) {
> > >      SecondLevelPagingEntry = AllocateZeroPages (1);
> > >      if (SecondLevelPagingEntry == NULL) {
> > > -      DEBUG ((DEBUG_ERROR,"Could not Alloc LVL4 PT. \n"));
> > > +      DEBUG ((DEBUG_ERROR,"Could not Alloc LVL4 or LVL5 PT. \n"));
> > >        return NULL;
> > >      }
> > >      FlushPageTableMemory (VtdIndex, (UINTN)SecondLevelPagingEntry,
> > > EFI_PAGES_TO_SIZE(1)); @@ -197,66 +226,109 @@
> > > CreateSecondLevelPagingEntryTable (
> > >      return SecondLevelPagingEntry;
> > >    }
> > >
> > > -  Lvl4Start = RShiftU64 (BaseAddress, 39) & 0x1FF;
> > > -  Lvl4End = RShiftU64 (EndAddress - 1, 39) & 0x1FF;
> > > +  if (Is5LevelPaging) {
> > > +    Lvl5Start = RShiftU64 (BaseAddress, 48) & 0x1FF;
> > > +    Lvl5End = RShiftU64 (EndAddress - 1, 48) & 0x1FF;
> > > +    DEBUG ((DEBUG_INFO,"  Lvl5Start - 0x%x, Lvl5End - 0x%x\n",
> > > + Lvl5Start,
> > > Lvl5End));
> > >
> > > -  DEBUG ((DEBUG_INFO,"  Lvl4Start - 0x%x, Lvl4End - 0x%x\n",
> > > Lvl4Start, Lvl4End));
> > > +    Lvl4Start = RShiftU64 (BaseAddress, 39) & 0x1FF;
> > > +    Lvl4End = RShiftU64 (EndAddress - 1, 39) & 0x1FF;
> > >
> > > -  Lvl4PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> > > *)SecondLevelPagingEntry;
> > > -  for (Index4 = Lvl4Start; Index4 <= Lvl4End; Index4++) {
> > > -    if (Lvl4PtEntry[Index4].Uint64 == 0) {
> > > -      Lvl4PtEntry[Index4].Uint64 = (UINT64)(UINTN)AllocateZeroPages (1);
> > > -      if (Lvl4PtEntry[Index4].Uint64 == 0) {
> > > -        DEBUG ((DEBUG_ERROR,"!!!!!! ALLOCATE LVL4 PAGE FAIL
> > > (0x%x)!!!!!!\n", Index4));
> > > -        ASSERT(FALSE);
> > > -        return NULL;
> > > -      }
> > > -      FlushPageTableMemory (VtdIndex,
> (UINTN)Lvl4PtEntry[Index4].Uint64,
> > > SIZE_4KB);
> > > -      SetSecondLevelPagingEntryAttribute (&Lvl4PtEntry[Index4],
> > > EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);
> > > -    }
> > > +    Lvl4PagesStart = (Lvl5Start<<9) | Lvl4Start;
> > > +    Lvl4PagesEnd = (Lvl5End<<9) | Lvl4End;
> > > +    DEBUG ((DEBUG_INFO,"  Lvl4PagesStart - 0x%x, Lvl4PagesEnd -
> > > + 0x%x\n",
> > > Lvl4PagesStart, Lvl4PagesEnd));
> > >
> > > -    Lvl3Start = RShiftU64 (BaseAddress, 30) & 0x1FF;
> > > -    if (ALIGN_VALUE_LOW(BaseAddress + SIZE_1GB, SIZE_1GB) <=
> > > EndAddress) {
> > > -      Lvl3End = SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY) - 1;
> > > -    } else {
> > > -      Lvl3End = RShiftU64 (EndAddress - 1, 30) & 0x1FF;
> > > +    Lvl5PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> > > *)SecondLevelPagingEntry;
> > > +  } else {
> > > +    Lvl5Start = RShiftU64 (BaseAddress, 48) & 0x1FF;
> > > +    Lvl5End = Lvl5Start;
> > > +
> > > +    Lvl4Start = RShiftU64 (BaseAddress, 39) & 0x1FF;
> > > +    Lvl4End = RShiftU64 (EndAddress - 1, 39) & 0x1FF;
> > > +    DEBUG ((DEBUG_INFO,"  Lvl4Start - 0x%x, Lvl4End - 0x%x\n",
> > > + Lvl4Start,
> > > Lvl4End));
> > > +
> > > +    Lvl4PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> > > *)SecondLevelPagingEntry;
> > > +  }
> > > +
> > > +  for (Index5 = Lvl5Start; Index5 <= Lvl5End; Index5++) {
> > > +    if (Is5LevelPaging) {
> > > +      if (Lvl5PtEntry[Index5].Uint64 == 0) {
> > > +        Lvl5PtEntry[Index5].Uint64 = (UINT64)(UINTN)AllocateZeroPages (1);
> > > +        if (Lvl5PtEntry[Index5].Uint64 == 0) {
> > > +          DEBUG ((DEBUG_ERROR,"!!!!!! ALLOCATE LVL4 PAGE FAIL
> > > (0x%x)!!!!!!\n", Index5));
> > > +          ASSERT(FALSE);
> > > +          return NULL;
> > > +        }
> > > +        FlushPageTableMemory (VtdIndex,
> > > + (UINTN)Lvl5PtEntry[Index5].Uint64,
> > > SIZE_4KB);
> > > +        SetSecondLevelPagingEntryAttribute (&Lvl5PtEntry[Index5],
> > > EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);
> > > +      }
> > > +      Lvl4Start = Lvl4PagesStart & 0x1FF;
> > > +      if (((Index5+1)<<9) > Lvl4PagesEnd) {
> > > +        Lvl4End = SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY) -
> 1;;
> > > +        Lvl4PagesStart = (Index5+1)<<9;
> > > +      } else {
> > > +        Lvl4End = Lvl4PagesEnd & 0x1FF;
> > > +      }
> > > +      DEBUG ((DEBUG_INFO,"  Lvl5(0x%x): Lvl4Start - 0x%x, Lvl4End -
> > > + 0x%x\n",
> > > Index5, Lvl4Start, Lvl4End));
> > > +      Lvl4PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> > > *)(UINTN)VTD_64BITS_ADDRESS(Lvl5PtEntry[Index5].Bits.AddressLo,
> > > Lvl5PtEntry[Index5].Bits.AddressHi);
> > >      }
> > > -    DEBUG ((DEBUG_INFO,"  Lvl4(0x%x): Lvl3Start - 0x%x, Lvl3End -
> 0x%x\n",
> > > Index4, Lvl3Start, Lvl3End));
> > >
> > > -    Lvl3PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> > > *)(UINTN)VTD_64BITS_ADDRESS(Lvl4PtEntry[Index4].Bits.AddressLo,
> > > Lvl4PtEntry[Index4].Bits.AddressHi);
> > > -    for (Index3 = Lvl3Start; Index3 <= Lvl3End; Index3++) {
> > > -      if (Lvl3PtEntry[Index3].Uint64 == 0) {
> > > -        Lvl3PtEntry[Index3].Uint64 = (UINT64)(UINTN)AllocateZeroPages (1);
> > > -        if (Lvl3PtEntry[Index3].Uint64 == 0) {
> > > -          DEBUG ((DEBUG_ERROR,"!!!!!! ALLOCATE LVL3 PAGE FAIL (0x%x,
> > > 0x%x)!!!!!!\n", Index4, Index3));
> > > +    for (Index4 = Lvl4Start; Index4 <= Lvl4End; Index4++) {
> > > +      if (Lvl4PtEntry[Index4].Uint64 == 0) {
> > > +        Lvl4PtEntry[Index4].Uint64 = (UINT64)(UINTN)AllocateZeroPages (1);
> > > +        if (Lvl4PtEntry[Index4].Uint64 == 0) {
> > > +          DEBUG ((DEBUG_ERROR,"!!!!!! ALLOCATE LVL4 PAGE FAIL
> > > (0x%x)!!!!!!\n", Index4));
> > >            ASSERT(FALSE);
> > >            return NULL;
> > >          }
> > > -        FlushPageTableMemory (VtdIndex,
> (UINTN)Lvl3PtEntry[Index3].Uint64,
> > > SIZE_4KB);
> > > -        SetSecondLevelPagingEntryAttribute (&Lvl3PtEntry[Index3],
> > > EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);
> > > +        FlushPageTableMemory (VtdIndex,
> > > + (UINTN)Lvl4PtEntry[Index4].Uint64,
> > > SIZE_4KB);
> > > +        SetSecondLevelPagingEntryAttribute (&Lvl4PtEntry[Index4],
> > > EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);
> > >        }
> > >
> > > -      Lvl2PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> > > *)(UINTN)VTD_64BITS_ADDRESS(Lvl3PtEntry[Index3].Bits.AddressLo,
> > > Lvl3PtEntry[Index3].Bits.AddressHi);
> > > -      for (Index2 = 0; Index2 <
> > > SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY); Index2++) {
> > > -        Lvl2PtEntry[Index2].Uint64 = BaseAddress;
> > > -        SetSecondLevelPagingEntryAttribute (&Lvl2PtEntry[Index2],
> > > IoMmuAccess);
> > > -        Lvl2PtEntry[Index2].Bits.PageSize = 1;
> > > -        BaseAddress += SIZE_2MB;
> > > +      Lvl3Start = RShiftU64 (BaseAddress, 30) & 0x1FF;
> > > +      if (ALIGN_VALUE_LOW(BaseAddress + SIZE_1GB, SIZE_1GB) <=
> > > EndAddress) {
> > > +        Lvl3End = SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY) - 1;
> > > +      } else {
> > > +        Lvl3End = RShiftU64 (EndAddress - 1, 30) & 0x1FF;
> > > +      }
> > > +      DEBUG ((DEBUG_INFO,"  Lvl4(0x%x): Lvl3Start - 0x%x, Lvl3End -
> > > + 0x%x\n",
> > > Index4, Lvl3Start, Lvl3End));
> > > +
> > > +      Lvl3PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> > > *)(UINTN)VTD_64BITS_ADDRESS(Lvl4PtEntry[Index4].Bits.AddressLo,
> > > Lvl4PtEntry[Index4].Bits.AddressHi);
> > > +      for (Index3 = Lvl3Start; Index3 <= Lvl3End; Index3++) {
> > > +        if (Lvl3PtEntry[Index3].Uint64 == 0) {
> > > +          Lvl3PtEntry[Index3].Uint64 = (UINT64)(UINTN)AllocateZeroPages
> (1);
> > > +          if (Lvl3PtEntry[Index3].Uint64 == 0) {
> > > +            DEBUG ((DEBUG_ERROR,"!!!!!! ALLOCATE LVL3 PAGE FAIL
> > > + (0x%x,
> > > 0x%x)!!!!!!\n", Index4, Index3));
> > > +            ASSERT(FALSE);
> > > +            return NULL;
> > > +          }
> > > +          FlushPageTableMemory (VtdIndex,
> > > + (UINTN)Lvl3PtEntry[Index3].Uint64,
> > > SIZE_4KB);
> > > +          SetSecondLevelPagingEntryAttribute (&Lvl3PtEntry[Index3],
> > > EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);
> > > +        }
> > > +
> > > +        Lvl2PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> > > *)(UINTN)VTD_64BITS_ADDRESS(Lvl3PtEntry[Index3].Bits.AddressLo,
> > > Lvl3PtEntry[Index3].Bits.AddressHi);
> > > +        for (Index2 = 0; Index2 <
> > > SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY); Index2++) {
> > > +          Lvl2PtEntry[Index2].Uint64 = BaseAddress;
> > > +          SetSecondLevelPagingEntryAttribute (&Lvl2PtEntry[Index2],
> > > IoMmuAccess);
> > > +          Lvl2PtEntry[Index2].Bits.PageSize = 1;
> > > +          BaseAddress += SIZE_2MB;
> > > +          if (BaseAddress >= MemoryLimit) {
> > > +            break;
> > > +          }
> > > +        }
> > > +        FlushPageTableMemory (VtdIndex, (UINTN)Lvl2PtEntry,
> > > + SIZE_4KB);
> > >          if (BaseAddress >= MemoryLimit) {
> > >            break;
> > >          }
> > >        }
> > > -      FlushPageTableMemory (VtdIndex, (UINTN)Lvl2PtEntry, SIZE_4KB);
> > > +      FlushPageTableMemory (VtdIndex, (UINTN)&Lvl3PtEntry[Lvl3Start],
> > > (UINTN)&Lvl3PtEntry[Lvl3End + 1] - (UINTN)&Lvl3PtEntry[Lvl3Start]);
> > >        if (BaseAddress >= MemoryLimit) {
> > >          break;
> > >        }
> > >      }
> > > -    FlushPageTableMemory (VtdIndex, (UINTN)&Lvl3PtEntry[Lvl3Start],
> > > (UINTN)&Lvl3PtEntry[Lvl3End + 1] - (UINTN)&Lvl3PtEntry[Lvl3Start]);
> > > -    if (BaseAddress >= MemoryLimit) {
> > > -      break;
> > > -    }
> > > +    FlushPageTableMemory (VtdIndex, (UINTN)&Lvl4PtEntry[Lvl4Start],
> > > (UINTN)&Lvl4PtEntry[Lvl4End + 1] - (UINTN)&Lvl4PtEntry[Lvl4Start]);
> > >    }
> > > -  FlushPageTableMemory (VtdIndex, (UINTN)&Lvl4PtEntry[Lvl4Start],
> > > (UINTN)&Lvl4PtEntry[Lvl4End + 1] - (UINTN)&Lvl4PtEntry[Lvl4Start]);
> > > +  FlushPageTableMemory (VtdIndex, (UINTN)&Lvl5PtEntry[Lvl5Start],
> > > (UINTN)&Lvl5PtEntry[Lvl5End + 1] - (UINTN)&Lvl5PtEntry[Lvl5Start]);
> > >
> > >    return SecondLevelPagingEntry;
> > >  }
> > > @@ -266,26 +338,28 @@ CreateSecondLevelPagingEntryTable (
> > >
> > >    @param[in]  VtdIndex                    The index of the VTd engine.
> > >    @param[in]  IoMmuAccess                 The IOMMU access.
> > > +  @param[in]  Is5LevelPaging              If it is the 5 level paging.
> > >
> > >    @return The second level paging entry.
> > >  **/
> > >  VTD_SECOND_LEVEL_PAGING_ENTRY *
> > >  CreateSecondLevelPagingEntry (
> > >    IN UINTN   VtdIndex,
> > > -  IN UINT64  IoMmuAccess
> > > +  IN UINT64  IoMmuAccess,
> > > +  IN BOOLEAN Is5LevelPaging
> > >    )
> > >  {
> > >    VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry;
> > >
> > >    SecondLevelPagingEntry = NULL;
> > > -  SecondLevelPagingEntry = CreateSecondLevelPagingEntryTable
> > > (VtdIndex, SecondLevelPagingEntry, 0, mBelow4GMemoryLimit,
> > > IoMmuAccess);
> > > +  SecondLevelPagingEntry = CreateSecondLevelPagingEntryTable
> > > + (VtdIndex,
> > > SecondLevelPagingEntry, 0, mBelow4GMemoryLimit, IoMmuAccess,
> > > Is5LevelPaging);
> > >    if (SecondLevelPagingEntry == NULL) {
> > >      return NULL;
> > >    }
> > >
> > >    if (mAbove4GMemoryLimit != 0) {
> > >      ASSERT (mAbove4GMemoryLimit > BASE_4GB);
> > > -    SecondLevelPagingEntry = CreateSecondLevelPagingEntryTable
> (VtdIndex,
> > > SecondLevelPagingEntry, SIZE_4GB, mAbove4GMemoryLimit,
> IoMmuAccess);
> > > +    SecondLevelPagingEntry = CreateSecondLevelPagingEntryTable
> > > + (VtdIndex,
> > > SecondLevelPagingEntry, SIZE_4GB, mAbove4GMemoryLimit,
> IoMmuAccess,
> > > Is5LevelPaging);
> > >      if (SecondLevelPagingEntry == NULL) {
> > >        return NULL;
> > >      }
> > > @@ -326,11 +400,13 @@ SetupTranslationTable (
> > >  /**
> > >    Dump DMAR context entry table.
> > >
> > > -  @param[in]  RootEntry DMAR root entry.
> > > +  @param[in]  RootEntry       DMAR root entry.
> > > +  @param[in]  Is5LevelPaging  If it is the 5 level paging.
> > >  **/
> > >  VOID
> > >  DumpDmarContextEntryTable (
> > > -  IN VTD_ROOT_ENTRY *RootEntry
> > > +  IN VTD_ROOT_ENTRY *RootEntry,
> > > +  IN BOOLEAN Is5LevelPaging
> > >    )
> > >  {
> > >    UINTN                 Index;
> > > @@ -359,7 +435,7 @@ DumpDmarContextEntryTable (
> > >        if (ContextEntry[Index2].Bits.Present == 0) {
> > >          continue;
> > >        }
> > > -      DumpSecondLevelPagingEntry ((VOID
> > >
> *)(UINTN)VTD_64BITS_ADDRESS(ContextEntry[Index2].Bits.SecondLevelPage
> > > TranslationPointerLo,
> > > ContextEntry[Index2].Bits.SecondLevelPageTranslationPointerHi));
> > > +      DumpSecondLevelPagingEntry ((VOID
> > >
> *)(UINTN)VTD_64BITS_ADDRESS(ContextEntry[Index2].Bits.SecondLevelPage
> > > TranslationPointerLo,
> > > ContextEntry[Index2].Bits.SecondLevelPageTranslationPointerHi),
> > > Is5LevelPaging);
> > >      }
> > >    }
> > >    DEBUG ((DEBUG_INFO,"=========================\n"));
> > > @@ -368,17 +444,22 @@ DumpDmarContextEntryTable (
> > >  /**
> > >    Dump DMAR second level paging entry.
> > >
> > > -  @param[in]  SecondLevelPagingEntry The second level paging entry.
> > > +  @param[in]  SecondLevelPagingEntry  The second level paging entry.
> > > +  @param[in]  Is5LevelPaging          If it is the 5 level paging.
> > >  **/
> > >  VOID
> > >  DumpSecondLevelPagingEntry (
> > > -  IN VOID *SecondLevelPagingEntry
> > > +  IN VOID *SecondLevelPagingEntry,
> > > +  IN BOOLEAN Is5LevelPaging
> > >    )
> > >  {
> > > +  UINTN                          Index5;
> > >    UINTN                          Index4;
> > >    UINTN                          Index3;
> > >    UINTN                          Index2;
> > >    UINTN                          Index1;
> > > +  UINTN                          Lvl5IndexEnd;
> > > +  VTD_SECOND_LEVEL_PAGING_ENTRY  *Lvl5PtEntry;
> > >    VTD_SECOND_LEVEL_PAGING_ENTRY  *Lvl4PtEntry;
> > >    VTD_SECOND_LEVEL_PAGING_ENTRY  *Lvl3PtEntry;
> > >    VTD_SECOND_LEVEL_PAGING_ENTRY  *Lvl2PtEntry; @@ -386,38
> +467,53
> > @@
> > > DumpSecondLevelPagingEntry (
> > >
> > >    DEBUG ((DEBUG_VERBOSE,"================\n"));
> > >    DEBUG ((DEBUG_VERBOSE,"DMAR Second Level Page Table:\n"));
> > > +  DEBUG ((DEBUG_VERBOSE,"SecondLevelPagingEntry Base - 0x%x,
> > > Is5LevelPaging - %d\n", SecondLevelPagingEntry, Is5LevelPaging));
> > >
> > > -  DEBUG ((DEBUG_VERBOSE,"SecondLevelPagingEntry Base - 0x%x\n",
> > > SecondLevelPagingEntry));
> > > +  Lvl5IndexEnd = Is5LevelPaging ?
> > > SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY) : 1;
> > >    Lvl4PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> > > *)SecondLevelPagingEntry;
> > > -  for (Index4 = 0; Index4 <
> > > SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY); Index4++) {
> > > -    if (Lvl4PtEntry[Index4].Uint64 != 0) {
> > > -      DEBUG ((DEBUG_VERBOSE,"  Lvl4Pt Entry(0x%03x) - 0x%016lx\n",
> Index4,
> > > Lvl4PtEntry[Index4].Uint64));
> > > -    }
> > > -    if (Lvl4PtEntry[Index4].Uint64 == 0) {
> > > -      continue;
> > > -    }
> > > -    Lvl3PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> > > *)(UINTN)VTD_64BITS_ADDRESS(Lvl4PtEntry[Index4].Bits.AddressLo,
> > > Lvl4PtEntry[Index4].Bits.AddressHi);
> > > -    for (Index3 = 0; Index3 <
> > > SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY); Index3++) {
> > > -      if (Lvl3PtEntry[Index3].Uint64 != 0) {
> > > -        DEBUG ((DEBUG_VERBOSE,"    Lvl3Pt Entry(0x%03x) - 0x%016lx\n",
> > > Index3, Lvl3PtEntry[Index3].Uint64));
> > > +  Lvl5PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> > > *)SecondLevelPagingEntry;
> > > +
> > > +  for (Index5 = 0; Index5 < Lvl5IndexEnd; Index5++) {
> > > +    if (Is5LevelPaging) {
> > > +      if (Lvl5PtEntry[Index5].Uint64 != 0) {
> > > +        DEBUG ((DEBUG_VERBOSE,"  Lvl5Pt Entry(0x%03x) - 0x%016lx\n",
> > > Index5, Lvl5PtEntry[Index5].Uint64));
> > >        }
> > > -      if (Lvl3PtEntry[Index3].Uint64 == 0) {
> > > +      if (Lvl5PtEntry[Index5].Uint64 == 0) {
> > >          continue;
> > >        }
> > > +      Lvl4PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> > > *)(UINTN)VTD_64BITS_ADDRESS(Lvl5PtEntry[Index5].Bits.AddressLo,
> > > Lvl5PtEntry[Index5].Bits.AddressHi);
> > > +    }
> > >
> > > -      Lvl2PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> > > *)(UINTN)VTD_64BITS_ADDRESS(Lvl3PtEntry[Index3].Bits.AddressLo,
> > > Lvl3PtEntry[Index3].Bits.AddressHi);
> > > -      for (Index2 = 0; Index2 <
> > > SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY); Index2++) {
> > > -        if (Lvl2PtEntry[Index2].Uint64 != 0) {
> > > -          DEBUG ((DEBUG_VERBOSE,"      Lvl2Pt Entry(0x%03x) - 0x%016lx\n",
> > > Index2, Lvl2PtEntry[Index2].Uint64));
> > > +    for (Index4 = 0; Index4 <
> > > SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY); Index4++) {
> > > +      if (Lvl4PtEntry[Index4].Uint64 != 0) {
> > > +        DEBUG ((DEBUG_VERBOSE,"  Lvl4Pt Entry(0x%03x) - 0x%016lx\n",
> > > Index4, Lvl4PtEntry[Index4].Uint64));
> > > +      }
> > > +      if (Lvl4PtEntry[Index4].Uint64 == 0) {
> > > +        continue;
> > > +      }
> > > +      Lvl3PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> > > *)(UINTN)VTD_64BITS_ADDRESS(Lvl4PtEntry[Index4].Bits.AddressLo,
> > > Lvl4PtEntry[Index4].Bits.AddressHi);
> > > +      for (Index3 = 0; Index3 <
> > > SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY); Index3++) {
> > > +        if (Lvl3PtEntry[Index3].Uint64 != 0) {
> > > +          DEBUG ((DEBUG_VERBOSE,"   Lvl3Pt Entry(0x%03x) - 0x%016lx\n",
> > > Index3, Lvl3PtEntry[Index3].Uint64));
> > >          }
> > > -        if (Lvl2PtEntry[Index2].Uint64 == 0) {
> > > +        if (Lvl3PtEntry[Index3].Uint64 == 0) {
> > >            continue;
> > >          }
> > > -        if (Lvl2PtEntry[Index2].Bits.PageSize == 0) {
> > > -          Lvl1PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> > > *)(UINTN)VTD_64BITS_ADDRESS(Lvl2PtEntry[Index2].Bits.AddressLo,
> > > Lvl2PtEntry[Index2].Bits.AddressHi);
> > > -          for (Index1 = 0; Index1 <
> > > SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY); Index1++) {
> > > -            if (Lvl1PtEntry[Index1].Uint64 != 0) {
> > > -              DEBUG ((DEBUG_VERBOSE,"        Lvl1Pt Entry(0x%03x) -
> > 0x%016lx\n",
> > > Index1, Lvl1PtEntry[Index1].Uint64));
> > > +
> > > +        Lvl2PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> > > *)(UINTN)VTD_64BITS_ADDRESS(Lvl3PtEntry[Index3].Bits.AddressLo,
> > > Lvl3PtEntry[Index3].Bits.AddressHi);
> > > +        for (Index2 = 0; Index2 <
> > > SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY); Index2++) {
> > > +          if (Lvl2PtEntry[Index2].Uint64 != 0) {
> > > +            DEBUG ((DEBUG_VERBOSE,"    Lvl2Pt Entry(0x%03x) - 0x%016lx\n",
> > > Index2, Lvl2PtEntry[Index2].Uint64));
> > > +          }
> > > +          if (Lvl2PtEntry[Index2].Uint64 == 0) {
> > > +            continue;
> > > +          }
> > > +          if (Lvl2PtEntry[Index2].Bits.PageSize == 0) {
> > > +            Lvl1PtEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY
> > > *)(UINTN)VTD_64BITS_ADDRESS(Lvl2PtEntry[Index2].Bits.AddressLo,
> > > Lvl2PtEntry[Index2].Bits.AddressHi);
> > > +            for (Index1 = 0; Index1 <
> > > SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY); Index1++) {
> > > +              if (Lvl1PtEntry[Index1].Uint64 != 0) {
> > > +                DEBUG ((DEBUG_VERBOSE,"      Lvl1Pt Entry(0x%03x) -
> > 0x%016lx\n",
> > > Index1, Lvl1PtEntry[Index1].Uint64));
> > > +              }
> > >              }
> > >            }
> > >          }
> > > @@ -510,6 +606,7 @@ PageAttributeToLength (
> > >    @param[in]   VtdIndex                 The index used to identify a VTd engine.
> > >    @param[in]   SecondLevelPagingEntry   The second level paging entry in
> > > VTd table for the device.
> > >    @param[in]   Address                  The address to be checked.
> > > +  @param[in]   Is5LevelPaging           If it is the 5 level paging.
> > >    @param[out]  PageAttributes           The page attribute of the page entry.
> > >
> > >    @return The page entry.
> > > @@ -519,6 +616,7 @@ GetSecondLevelPageTableEntry (
> > >    IN  UINTN                         VtdIndex,
> > >    IN  VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry,
> > >    IN  PHYSICAL_ADDRESS              Address,
> > > +  IN  BOOLEAN                       Is5LevelPaging,
> > >    OUT PAGE_ATTRIBUTE                *PageAttribute
> > >    )
> > >  {
> > > @@ -526,17 +624,38 @@ GetSecondLevelPageTableEntry (
> > >    UINTN                 Index2;
> > >    UINTN                 Index3;
> > >    UINTN                 Index4;
> > > +  UINTN                 Index5;
> > >    UINT64                *L1PageTable;
> > >    UINT64                *L2PageTable;
> > >    UINT64                *L3PageTable;
> > >    UINT64                *L4PageTable;
> > > +  UINT64                *L5PageTable;
> > >
> > > +  Index5 = ((UINTN)RShiftU64 (Address, 48)) &
> PAGING_VTD_INDEX_MASK;
> > >    Index4 = ((UINTN)RShiftU64 (Address, 39)) &
> PAGING_VTD_INDEX_MASK;
> > >    Index3 = ((UINTN)Address >> 30) & PAGING_VTD_INDEX_MASK;
> > >    Index2 = ((UINTN)Address >> 21) & PAGING_VTD_INDEX_MASK;
> > >    Index1 = ((UINTN)Address >> 12) & PAGING_VTD_INDEX_MASK;
> > >
> > > -  L4PageTable = (UINT64 *)SecondLevelPagingEntry;
> > > +  if (Is5LevelPaging) {
> > > +    L5PageTable = (UINT64 *)SecondLevelPagingEntry;
> > > +    if (L5PageTable[Index5] == 0) {
> > > +      L5PageTable[Index5] = (UINT64)(UINTN)AllocateZeroPages (1);
> > > +      if (L5PageTable[Index5] == 0) {
> > > +        DEBUG ((DEBUG_ERROR,"!!!!!! ALLOCATE LVL5 PAGE FAIL
> > > (0x%x)!!!!!!\n", Index4));
> > > +        ASSERT(FALSE);
> > > +        *PageAttribute = PageNone;
> > > +        return NULL;
> > > +      }
> > > +      FlushPageTableMemory (VtdIndex, (UINTN)L5PageTable[Index5],
> > > SIZE_4KB);
> > > +      SetSecondLevelPagingEntryAttribute
> > > ((VTD_SECOND_LEVEL_PAGING_ENTRY *)&L5PageTable[Index5],
> > > EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);
> > > +      FlushPageTableMemory (VtdIndex, (UINTN)&L5PageTable[Index5],
> > > sizeof(L5PageTable[Index5]));
> > > +    }
> > > +    L4PageTable = (UINT64 *)(UINTN)(L5PageTable[Index5] &
> > > PAGING_4K_ADDRESS_MASK_64);
> > > +  } else {
> > > +    L4PageTable = (UINT64 *)SecondLevelPagingEntry;  }
> > > +
> > >    if (L4PageTable[Index4] == 0) {
> > >      L4PageTable[Index4] = (UINT64)(UINTN)AllocateZeroPages (1);
> > >      if (L4PageTable[Index4] == 0) {
> > > @@ -785,7 +904,7 @@ SetSecondLevelPagingAttribute (
> > >    }
> > >
> > >    while (Length != 0) {
> > > -    PageEntry = GetSecondLevelPageTableEntry (VtdIndex,
> > > SecondLevelPagingEntry, BaseAddress, &PageAttribute);
> > > +    PageEntry = GetSecondLevelPageTableEntry (VtdIndex,
> > > SecondLevelPagingEntry, BaseAddress,
> > > mVtdUnitInformation[VtdIndex].Is5LevelPaging, &PageAttribute);
> > >      if (PageEntry == NULL) {
> > >        DEBUG ((DEBUG_ERROR, "PageEntry - NULL\n"));
> > >        return RETURN_UNSUPPORTED;
> > > @@ -913,7 +1032,7 @@ SetAccessAttribute (
> > >
> > >    if (ExtContextEntry != NULL) {
> > >      if (ExtContextEntry->Bits.Present == 0) {
> > > -      SecondLevelPagingEntry = CreateSecondLevelPagingEntry (VtdIndex,
> 0);
> > > +      SecondLevelPagingEntry = CreateSecondLevelPagingEntry
> > > + (VtdIndex, 0,
> > > mVtdUnitInformation[VtdIndex].Is5LevelPaging);
> > >        DEBUG ((DEBUG_VERBOSE,"SecondLevelPagingEntry - 0x%x (S%04x
> > > B%02x D%02x F%02x) New\n", SecondLevelPagingEntry, Segment,
> > > SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.Function));
> > >        Pt = (UINT64)RShiftU64 ((UINT64)(UINTN)SecondLevelPagingEntry,
> > > 12);
> > >
> > > @@ -922,7 +1041,7 @@ SetAccessAttribute (
> > >        ExtContextEntry->Bits.DomainIdentifier = DomainIdentifier;
> > >        ExtContextEntry->Bits.Present = 1;
> > >        FlushPageTableMemory (VtdIndex, (UINTN)ExtContextEntry,
> > > sizeof(*ExtContextEntry));
> > > -      DumpDmarExtContextEntryTable
> > > (mVtdUnitInformation[VtdIndex].ExtRootEntryTable);
> > > +      DumpDmarExtContextEntryTable
> > > (mVtdUnitInformation[VtdIndex].ExtRootEntryTable,
> > > mVtdUnitInformation[VtdIndex].Is5LevelPaging);
> > >        mVtdUnitInformation[VtdIndex].HasDirtyContext = TRUE;
> > >      } else {
> > >        SecondLevelPagingEntry = (VOID
> > > *)(UINTN)VTD_64BITS_ADDRESS(ExtContextEntry-
> > > >Bits.SecondLevelPageTranslationPointerLo, ExtContextEntry-
> > > >Bits.SecondLevelPageTranslationPointerHi);
> > > @@ -930,7 +1049,7 @@ SetAccessAttribute (
> > >      }
> > >    } else if (ContextEntry != NULL) {
> > >      if (ContextEntry->Bits.Present == 0) {
> > > -      SecondLevelPagingEntry = CreateSecondLevelPagingEntry (VtdIndex,
> 0);
> > > +      SecondLevelPagingEntry = CreateSecondLevelPagingEntry
> > > + (VtdIndex, 0,
> > > mVtdUnitInformation[VtdIndex].Is5LevelPaging);
> > >        DEBUG ((DEBUG_VERBOSE,"SecondLevelPagingEntry - 0x%x (S%04x
> > > B%02x D%02x F%02x) New\n", SecondLevelPagingEntry, Segment,
> > > SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.Function));
> > >        Pt = (UINT64)RShiftU64 ((UINT64)(UINTN)SecondLevelPagingEntry,
> > > 12);
> > >
> > > @@ -939,7 +1058,7 @@ SetAccessAttribute (
> > >        ContextEntry->Bits.DomainIdentifier = DomainIdentifier;
> > >        ContextEntry->Bits.Present = 1;
> > >        FlushPageTableMemory (VtdIndex, (UINTN)ContextEntry,
> > > sizeof(*ContextEntry));
> > > -      DumpDmarContextEntryTable
> > > (mVtdUnitInformation[VtdIndex].RootEntryTable);
> > > +      DumpDmarContextEntryTable
> > > (mVtdUnitInformation[VtdIndex].RootEntryTable,
> > > mVtdUnitInformation[VtdIndex].Is5LevelPaging);
> > >        mVtdUnitInformation[VtdIndex].HasDirtyContext = TRUE;
> > >      } else {
> > >        SecondLevelPagingEntry = (VOID
> > > *)(UINTN)VTD_64BITS_ADDRESS(ContextEntry-
> > > >Bits.SecondLevelPageTranslationPointerLo, ContextEntry-
> > > >Bits.SecondLevelPageTranslationPointerHi);
> > > @@ -1000,7 +1119,7 @@ AlwaysEnablePageAttribute (
> > >
> > >    if (mVtdUnitInformation[VtdIndex].FixedSecondLevelPagingEntry == 0) {
> > >      DEBUG((DEBUG_INFO, "CreateSecondLevelPagingEntry - %d\n",
> > > VtdIndex));
> > > -    mVtdUnitInformation[VtdIndex].FixedSecondLevelPagingEntry =
> > > CreateSecondLevelPagingEntry (VtdIndex, EDKII_IOMMU_ACCESS_READ |
> > > EDKII_IOMMU_ACCESS_WRITE);
> > > +    mVtdUnitInformation[VtdIndex].FixedSecondLevelPagingEntry =
> > > CreateSecondLevelPagingEntry (VtdIndex, EDKII_IOMMU_ACCESS_READ |
> > > EDKII_IOMMU_ACCESS_WRITE,
> > > mVtdUnitInformation[VtdIndex].Is5LevelPaging);
> > >    }
> > >
> > >    SecondLevelPagingEntry =
> > > mVtdUnitInformation[VtdIndex].FixedSecondLevelPagingEntry;
> > > diff --git
> > >
> a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTableEx.
> > > c
> > >
> b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTableEx.
> > > c
> > > index 0ed9e3ca..3918eeee 100644
> > > ---
> > >
> a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTableEx.
> > > c
> > > +++
> > >
> b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTableEx.
> > > c
> > > @@ -78,11 +78,32 @@ CreateExtContextEntry (
> > >
> > >      DEBUG ((DEBUG_INFO,"DOMAIN: S%04x, B%02x D%02x F%02x\n",
> > > mVtdUnitInformation[VtdIndex].Segment, SourceId.Bits.Bus,
> > > SourceId.Bits.Device, SourceId.Bits.Function));
> > >
> > > -    if ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW & BIT2) == 0)
> {
> > > -      DEBUG((DEBUG_ERROR, "!!!! 4-level page-table is not supported on
> > > VTD %d !!!!\n", VtdIndex));
> > > +    mVtdUnitInformation[VtdIndex].Is5LevelPaging = FALSE;
> > > +    if ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW & BIT3) != 0)
> {
> > > +      if ((PcdGet8(PcdVTdPolicyPropertyMask) & BIT3) != 0) {
> > > +        DEBUG((DEBUG_ERROR, "Force to use 4-level page-table on VTD
> > > + %d\n",
> > > VtdIndex));
> > > +        ExtContextEntry->Bits.AddressWidth = 0x2;
> > > +      } if ((PcdGet8(PcdVTdPolicyPropertyMask) & BIT4) != 0) {
> > > +        DEBUG((DEBUG_ERROR, "Force to use 5-level page-table on VTD
> > > + %d\n",
> > > VtdIndex));
> > > +        ExtContextEntry->Bits.AddressWidth = 0x3;
> > > +        mVtdUnitInformation[VtdIndex].Is5LevelPaging = TRUE;
> > > +      } else {
> > > +        if (mAcpiDmarTable->HostAddressWidth > 48) {
> > > +          DEBUG((DEBUG_ERROR, "Using 5-level page-table on VTD %d\n",
> > > VtdIndex));
> > > +          ExtContextEntry->Bits.AddressWidth = 0x3;
> > > +          mVtdUnitInformation[VtdIndex].Is5LevelPaging = TRUE;
> > > +        } else {
> > > +          DEBUG((DEBUG_ERROR, "Using 4-level page-table on VTD %d\n",
> > > VtdIndex));
> > > +          ExtContextEntry->Bits.AddressWidth = 0x2;
> > > +        }
> > > +      }
> > > +    } else if ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW &
> > > + BIT2) !=
> > > 0) {
> > > +      DEBUG((DEBUG_ERROR, "Using 4-level page-table on VTD %d\n",
> > > VtdIndex));
> > > +      ExtContextEntry->Bits.AddressWidth = 0x2;
> > > +    } else {
> > > +      DEBUG((DEBUG_ERROR, "!!!! Page-table type is not supported on
> > > VTD %d !!!!\n", VtdIndex));
> > >        return EFI_UNSUPPORTED;
> > >      }
> > > -    ExtContextEntry->Bits.AddressWidth = 0x2;
> > >    }
> > >
> > >    FlushPageTableMemory (VtdIndex,
> > > (UINTN)mVtdUnitInformation[VtdIndex].ExtRootEntryTable,
> > > EFI_PAGES_TO_SIZE(EntryTablePages));
> > > @@ -93,11 +114,13 @@ CreateExtContextEntry (
> > >  /**
> > >    Dump DMAR extended context entry table.
> > >
> > > -  @param[in]  ExtRootEntry DMAR extended root entry.
> > > +  @param[in]  ExtRootEntry    DMAR extended root entry.
> > > +  @param[in]  Is5LevelPaging  If it is the 5 level paging.
> > >  **/
> > >  VOID
> > >  DumpDmarExtContextEntryTable (
> > > -  IN VTD_EXT_ROOT_ENTRY *ExtRootEntry
> > > +  IN VTD_EXT_ROOT_ENTRY *ExtRootEntry,  IN BOOLEAN Is5LevelPaging
> > >    )
> > >  {
> > >    UINTN                 Index;
> > > @@ -127,7 +150,7 @@ DumpDmarExtContextEntryTable (
> > >        if (ExtContextEntry[Index2].Bits.Present == 0) {
> > >          continue;
> > >        }
> > > -      DumpSecondLevelPagingEntry ((VOID
> > >
> *)(UINTN)VTD_64BITS_ADDRESS(ExtContextEntry[Index2].Bits.SecondLevelPa
> > > geTranslationPointerLo,
> > > ExtContextEntry[Index2].Bits.SecondLevelPageTranslationPointerHi));
> > > +      DumpSecondLevelPagingEntry ((VOID
> > >
> *)(UINTN)VTD_64BITS_ADDRESS(ExtContextEntry[Index2].Bits.SecondLevelPa
> > > geTranslationPointerLo,
> > > ExtContextEntry[Index2].Bits.SecondLevelPageTranslationPointerHi),
> > > Is5LevelPaging);
> > >      }
> > >
> > >      if (ExtRootEntry[Index].Bits.UpperPresent == 0) { diff --git
> > > a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/VtdReg.c
> > > b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/VtdReg.c
> > > index 699639ba..686d235f 100644
> > > --- a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/VtdReg.c
> > > +++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/VtdReg.c
> > > @@ -174,8 +174,14 @@ PrepareVtdConfig (
> > >      if ((mVtdUnitInformation[Index].CapReg.Bits.SLLPS & BIT0) == 0) {
> > >        DEBUG((DEBUG_WARN, "!!!! 2MB super page is not supported on
> VTD
> > > %d !!!!\n", Index));
> > >      }
> > > -    if ((mVtdUnitInformation[Index].CapReg.Bits.SAGAW & BIT2) == 0) {
> > > -      DEBUG((DEBUG_ERROR, "!!!! 4-level page-table is not supported on
> > > VTD %d !!!!\n", Index));
> > > +    if ((mVtdUnitInformation[Index].CapReg.Bits.SAGAW & BIT3) != 0) {
> > > +      DEBUG((DEBUG_INFO, "Support 5-level page-table on VTD %d\n",
> > > Index));
> > > +    }
> > > +    if ((mVtdUnitInformation[Index].CapReg.Bits.SAGAW & BIT2) != 0) {
> > > +      DEBUG((DEBUG_INFO, "Support 4-level page-table on VTD %d\n",
> > > Index));
> > > +    }
> > > +    if ((mVtdUnitInformation[Index].CapReg.Bits.SAGAW & (BIT3 |
> > > + BIT2)) == 0)
> > > {
> > > +      DEBUG((DEBUG_ERROR, "!!!! Page-table type 0x%X is not supported
> > > + on
> > > VTD %d !!!!\n", Index, mVtdUnitInformation[Index].CapReg.Bits.SAGAW));
> > >        return ;
> > >      }
> > >
> > > diff --git a/Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dec
> > > b/Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dec
> > > index 284820af..8f1edfe2 100644
> > > --- a/Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dec
> > > +++ b/Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dec
> > > @@ -95,6 +95,9 @@
> > >    #  BIT0: Enable IOMMU during boot (If DMAR table is installed in
> > > DXE. If VTD_INFO_PPI is installed in PEI.)
> > >    #  BIT1: Enable IOMMU when transfer control to OS (ExitBootService
> > > in normal boot. EndOfPEI in S3)
> > >    #  BIT2: Force no IOMMU access attribute request recording before
> > > DMAR table is installed.
> > > +  #  BIT3: Force to use 4 level paging.
> > > +  #  BIT4: If iommu support 5 level paging, force to use 5 level paging.
> > > +  #    (If both BIT3 and BIT4 are set, force to use 4 level paging.)
> > >    # @Prompt The policy for VTd driver behavior.
> > >
> > >
> gIntelSiliconPkgTokenSpaceGuid.PcdVTdPolicyPropertyMask|1|UINT8|0x000
> > > 00002
> > >
> > > --
> > > 2.16.2.windows.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#67666): https://edk2.groups.io/g/devel/message/67666
Mute This Topic: https://groups.io/mt/78331319/1813853
Group Owner: devel+owner at edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [edk2-devel-archive at redhat.com]
-=-=-=-=-=-=-=-=-=-=-=-






More information about the edk2-devel-archive mailing list