[PATCH v5] IntelSiliconPkg/VTd: Add iommu 5 level paging support


Sheng Wei
 

Hi Jiewen,
About the patch of support 5 level paging iommu.
Thank you for giving the review comments.
I have done all the update.
Could you give "review by" on this patch ?
Thank you.
BR
Sheng Wei

-----Original Message-----
From: Sheng, W
Sent: 2020年11月24日 13:44
To: Yao, Jiewen <jiewen.yao@...>; devel@edk2.groups.io
Cc: Ni, Ray <ray.ni@...>; Chaganty, Rangasai V
<rangasai.v.chaganty@...>; Huang, Jenny <jenny.huang@...>
Subject: RE: [PATCH v4] IntelSiliconPkg/VTd: Add iommu 5 level paging support

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,,posteri
d%3A2558558,20,2,0,78471874
Could we continue the patch review ?
BR
Sheng Wei

-----Original Message-----
From: Yao, Jiewen <jiewen.yao@...>
Sent: 2020年11月23日 16:44
To: Sheng, W <w.sheng@...>; devel@edk2.groups.io
Cc: Ni, Ray <ray.ni@...>; Chaganty, Rangasai V
<rangasai.v.chaganty@...>; Huang, Jenny <jenny.huang@...>
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@...>
Sent: Monday, November 23, 2020 4:04 PM
To: devel@edk2.groups.io
Cc: Ni, Ray <ray.ni@...>; Chaganty, Rangasai V
<rangasai.v.chaganty@...>; Yao, Jiewen <jiewen.yao@...>;
Huang, Jenny <jenny.huang@...>
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@...>
Cc: Ray Ni <ray.ni@...>
Cc: Rangasai V Chaganty <rangasai.v.chaganty@...>
Cc: Jiewen Yao <jiewen.yao@...>
Cc: Jenny Huang <jenny.huang@...>
---
.../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/TranslationT
ab
le.c
b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationT
ab
le.c
index 201d663d..6c786b40 100644
---
a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationT
ab
le.c
+++
b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationT
ab 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.SecondLevelPag
e
TranslationPointerLo,
ContextEntry[Index2].Bits.SecondLevelPageTranslationPointerHi));
+ DumpSecondLevelPagingEntry ((VOID
*)(UINTN)VTD_64BITS_ADDRESS(ContextEntry[Index2].Bits.SecondLevelPag
e
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.SecondLevel
Pa
geTranslationPointerLo,
ExtContextEntry[Index2].Bits.SecondLevelPageTranslationPointerHi));
+ DumpSecondLevelPagingEntry ((VOID
*)(UINTN)VTD_64BITS_ADDRESS(ExtContextEntry[Index2].Bits.SecondLevel
Pa
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


Sheng Wei
 

Hi Jenny,

Thank you for the review.

I add your name under " Reviewed-by " to the patch.

 

@Yao, Jiewen

Do you have more comments about this patch?

Thank you.

BR

Sheng Wei

 

> -----Original Message-----

> From: Huang, Jenny <jenny.huang@...>

> Sent: 2020124 11:33

> To: Sheng, W <w.sheng@...>; Yao, Jiewen <jiewen.yao@...>;

> devel@edk2.groups.io

> Cc: Ni, Ray <ray.ni@...>; Chaganty, Rangasai V

> <rangasai.v.chaganty@...>; Feng, Roger <roger.feng@...>

> Subject: RE: [PATCH v5] IntelSiliconPkg/VTd: Add iommu 5 level paging support

>

> Reviewed-by: Jenny Huang < jenny.huang@...>

>

> -----Original Message-----

> From: Sheng, W <w.sheng@...>

> Sent: Tuesday, December 1, 2020 7:03 PM

> To: Yao, Jiewen <jiewen.yao@...>; devel@edk2.groups.io

> Cc: Ni, Ray <ray.ni@...>; Chaganty, Rangasai V

> <rangasai.v.chaganty@...>; Huang, Jenny <jenny.huang@...>;

> Feng, Roger <roger.feng@...>

> Subject: [PATCH v5] IntelSiliconPkg/VTd: Add iommu 5 level paging support

>

> Hi Jiewen,

> About the patch of support 5 level paging iommu.

> Thank you for giving the review comments.

> I have done all the update.

> Could you give "review by" on this patch ?

> Thank you.

> BR

> Sheng Wei

>

>

> > -----Original Message-----

> > From: Sheng, W

> > Sent: 20201124 13:44

> > To: Yao, Jiewen <jiewen.yao@...>; devel@edk2.groups.io

> > Cc: Ni, Ray <ray.ni@...>; Chaganty, Rangasai V

> > <rangasai.v.chaganty@...>; Huang, Jenny <jenny.huang@...>

> > Subject: RE: [PATCH v4] IntelSiliconPkg/VTd: Add iommu 5 level paging

> > support

> >

> > 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,

> > ,posteri

> > d%3A2558558,20,2,0,78471874

> > Could we continue the patch review ?

> > BR

> > Sheng Wei

> >

> > > -----Original Message-----

> > > From: Yao, Jiewen <jiewen.yao@...>

> > > Sent: 20201123 16:44

> > > To: Sheng, W <w.sheng@...>; devel@edk2.groups.io

> > > Cc: Ni, Ray <ray.ni@...>; Chaganty, Rangasai V

> > > <rangasai.v.chaganty@...>; Huang, Jenny

> > > <jenny.huang@...>

> > > 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@...>

> > > > Sent: Monday, November 23, 2020 4:04 PM

> > > > To: devel@edk2.groups.io

> > > > Cc: Ni, Ray <ray.ni@...>; Chaganty, Rangasai V

> > > > <rangasai.v.chaganty@...>; Yao, Jiewen

> > > > <jiewen.yao@...>; Huang, Jenny <jenny.huang@...>

> > > > 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@...>

> > > > Cc: Ray Ni <ray.ni@...>

> > > > Cc: Rangasai V Chaganty <rangasai.v.chaganty@...>

> > > > Cc: Jiewen Yao <jiewen.yao@...>

> > > > Cc: Jenny Huang <jenny.huang@...>

> > > > ---

> > > >  .../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/Translatio

> > > > nT

> > > > ab

> > > > le.c

> > > > b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/Translatio

> > > > nT

> > > > ab

> > > > le.c

> > > > index 201d663d..6c786b40 100644

> > > > ---

> > > > a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/Translatio

> > > > nT

> > > > ab

> > > > le.c

> > > > +++

> > > > b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/Translatio

> > > > nT ab 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.SecondLevelP

> > > > ag

> > > > e

> > > > TranslationPointerLo,

> > > > ContextEntry[Index2].Bits.SecondLevelPageTranslationPointerHi));

> > > > +      DumpSecondLevelPagingEntry ((VOID

> > > > *)(UINTN)VTD_64BITS_ADDRESS(ContextEntry[Index2].Bits.SecondLevelP

> > > > ag

> > > > e

> > > > 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.SecondLev

> > > > el

> > > > Pa

> > > > geTranslationPointerLo,

> > > > ExtContextEntry[Index2].Bits.SecondLevelPageTranslationPointerHi))

> > > > ;

> > > > +      DumpSecondLevelPagingEntry ((VOID

> > > > *)(UINTN)VTD_64BITS_ADDRESS(ExtContextEntry[Index2].Bits.SecondLev

> > > > el

> > > > Pa

> > > > 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

 


Huang, Jenny <jenny.huang@...>
 

Reviewed-by: Jenny Huang < jenny.huang@...>

-----Original Message-----
From: Sheng, W <w.sheng@...>
Sent: Tuesday, December 1, 2020 7:03 PM
To: Yao, Jiewen <jiewen.yao@...>; devel@edk2.groups.io
Cc: Ni, Ray <ray.ni@...>; Chaganty, Rangasai V <rangasai.v.chaganty@...>; Huang, Jenny <jenny.huang@...>; Feng, Roger <roger.feng@...>
Subject: [PATCH v5] IntelSiliconPkg/VTd: Add iommu 5 level paging support

Hi Jiewen,
About the patch of support 5 level paging iommu.
Thank you for giving the review comments.
I have done all the update.
Could you give "review by" on this patch ?
Thank you.
BR
Sheng Wei


-----Original Message-----
From: Sheng, W
Sent: 2020年11月24日 13:44
To: Yao, Jiewen <jiewen.yao@...>; devel@edk2.groups.io
Cc: Ni, Ray <ray.ni@...>; Chaganty, Rangasai V
<rangasai.v.chaganty@...>; Huang, Jenny <jenny.huang@...>
Subject: RE: [PATCH v4] IntelSiliconPkg/VTd: Add iommu 5 level paging
support

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,
,posteri
d%3A2558558,20,2,0,78471874
Could we continue the patch review ?
BR
Sheng Wei

-----Original Message-----
From: Yao, Jiewen <jiewen.yao@...>
Sent: 2020年11月23日 16:44
To: Sheng, W <w.sheng@...>; devel@edk2.groups.io
Cc: Ni, Ray <ray.ni@...>; Chaganty, Rangasai V
<rangasai.v.chaganty@...>; Huang, Jenny
<jenny.huang@...>
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@...>
Sent: Monday, November 23, 2020 4:04 PM
To: devel@edk2.groups.io
Cc: Ni, Ray <ray.ni@...>; Chaganty, Rangasai V
<rangasai.v.chaganty@...>; Yao, Jiewen
<jiewen.yao@...>; Huang, Jenny <jenny.huang@...>
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@...>
Cc: Ray Ni <ray.ni@...>
Cc: Rangasai V Chaganty <rangasai.v.chaganty@...>
Cc: Jiewen Yao <jiewen.yao@...>
Cc: Jenny Huang <jenny.huang@...>
---
.../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/Translatio
nT
ab
le.c
b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/Translatio
nT
ab
le.c
index 201d663d..6c786b40 100644
---
a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/Translatio
nT
ab
le.c
+++
b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/Translatio
nT ab 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.SecondLevelP
ag
e
TranslationPointerLo,
ContextEntry[Index2].Bits.SecondLevelPageTranslationPointerHi));
+ DumpSecondLevelPagingEntry ((VOID
*)(UINTN)VTD_64BITS_ADDRESS(ContextEntry[Index2].Bits.SecondLevelP
ag
e
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.SecondLev
el
Pa
geTranslationPointerLo,
ExtContextEntry[Index2].Bits.SecondLevelPageTranslationPointerHi))
;
+ DumpSecondLevelPagingEntry ((VOID
*)(UINTN)VTD_64BITS_ADDRESS(ExtContextEntry[Index2].Bits.SecondLev
el
Pa
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


Sheng Wei
 

Hi Ray,

Could you help to merge the patch of support 5 level paging iommu to edk2platform branch?

Do you need more check ?

Thank you.

BR

Sheng Wei

 

From: Sheng, W
Sent: 2020124 11:44
To: Huang, Jenny <jenny.huang@...>; Yao, Jiewen <jiewen.yao@...>; devel@edk2.groups.io
Cc: Ni, Ray <ray.ni@...>; Chaganty, Rangasai V <rangasai.v.chaganty@...>; Feng, Roger <roger.feng@...>
Subject: RE: [PATCH v5] IntelSiliconPkg/VTd: Add iommu 5 level paging support

 

Hi Jenny,

Thank you for the review.

I add your name under " Reviewed-by " to the patch.

 

@Yao, Jiewen

Do you have more comments about this patch?

Thank you.

BR

Sheng Wei

 

> -----Original Message-----

> From: Huang, Jenny <jenny.huang@...>

> Sent: 2020124 11:33

> To: Sheng, W <w.sheng@...>; Yao, Jiewen <jiewen.yao@...>;

> devel@edk2.groups.io

> Cc: Ni, Ray <ray.ni@...>; Chaganty, Rangasai V

> <rangasai.v.chaganty@...>; Feng, Roger <roger.feng@...>

> Subject: RE: [PATCH v5] IntelSiliconPkg/VTd: Add iommu 5 level paging support

>

> Reviewed-by: Jenny Huang < jenny.huang@...>

>

> -----Original Message-----

> From: Sheng, W <w.sheng@...>

> Sent: Tuesday, December 1, 2020 7:03 PM

> To: Yao, Jiewen <jiewen.yao@...>; devel@edk2.groups.io

> Cc: Ni, Ray <ray.ni@...>; Chaganty, Rangasai V

> <rangasai.v.chaganty@...>; Huang, Jenny <jenny.huang@...>;

> Feng, Roger <roger.feng@...>

> Subject: [PATCH v5] IntelSiliconPkg/VTd: Add iommu 5 level paging support

>

> Hi Jiewen,

> About the patch of support 5 level paging iommu.

> Thank you for giving the review comments.

> I have done all the update.

> Could you give "review by" on this patch ?

> Thank you.

> BR

> Sheng Wei

>

>

> > -----Original Message-----

> > From: Sheng, W

> > Sent: 20201124 13:44

> > To: Yao, Jiewen <jiewen.yao@...>; devel@edk2.groups.io

> > Cc: Ni, Ray <ray.ni@...>; Chaganty, Rangasai V

> > <rangasai.v.chaganty@...>; Huang, Jenny <jenny.huang@...>

> > Subject: RE: [PATCH v4] IntelSiliconPkg/VTd: Add iommu 5 level paging

> > support

> >

> > 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,

> > ,posteri

> > d%3A2558558,20,2,0,78471874

> > Could we continue the patch review ?

> > BR

> > Sheng Wei

> >

> > > -----Original Message-----

> > > From: Yao, Jiewen <jiewen.yao@...>

> > > Sent: 20201123 16:44

> > > To: Sheng, W <w.sheng@...>; devel@edk2.groups.io

> > > Cc: Ni, Ray <ray.ni@...>; Chaganty, Rangasai V

> > > <rangasai.v.chaganty@...>; Huang, Jenny

> > > <jenny.huang@...>

> > > 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@...>

> > > > Sent: Monday, November 23, 2020 4:04 PM

> > > > To: devel@edk2.groups.io

> > > > Cc: Ni, Ray <ray.ni@...>; Chaganty, Rangasai V

> > > > <rangasai.v.chaganty@...>; Yao, Jiewen

> > > > <jiewen.yao@...>; Huang, Jenny <jenny.huang@...>

> > > > 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@...>

> > > > Cc: Ray Ni <ray.ni@...>

> > > > Cc: Rangasai V Chaganty <rangasai.v.chaganty@...>

> > > > Cc: Jiewen Yao <jiewen.yao@...>

> > > > Cc: Jenny Huang <jenny.huang@...>

> > > > ---

> > > >  .../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/Translatio

> > > > nT

> > > > ab

> > > > le.c

> > > > b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/Translatio

> > > > nT

> > > > ab

> > > > le.c

> > > > index 201d663d..6c786b40 100644

> > > > ---

> > > > a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/Translatio

> > > > nT

> > > > ab

> > > > le.c

> > > > +++

> > > > b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/Translatio

> > > > nT ab 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.SecondLevelP

> > > > ag

> > > > e

> > > > TranslationPointerLo,

> > > > ContextEntry[Index2].Bits.SecondLevelPageTranslationPointerHi));

> > > > +      DumpSecondLevelPagingEntry ((VOID

> > > > *)(UINTN)VTD_64BITS_ADDRESS(ContextEntry[Index2].Bits.SecondLevelP

> > > > ag

> > > > e

> > > > 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.SecondLev

> > > > el

> > > > Pa

> > > > geTranslationPointerLo,

> > > > ExtContextEntry[Index2].Bits.SecondLevelPageTranslationPointerHi))

> > > > ;

> > > > +      DumpSecondLevelPagingEntry ((VOID

> > > > *)(UINTN)VTD_64BITS_ADDRESS(ExtContextEntry[Index2].Bits.SecondLev

> > > > el

> > > > Pa

> > > > 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

 


Ni, Ray
 

Acked-by: Ray Ni <ray.ni@...>

-----Original Message-----
From: Huang, Jenny <jenny.huang@...>
Sent: Friday, December 4, 2020 11:33 AM
To: Sheng, W <w.sheng@...>; Yao, Jiewen <jiewen.yao@...>;
devel@edk2.groups.io
Cc: Ni, Ray <ray.ni@...>; Chaganty, Rangasai V
<rangasai.v.chaganty@...>; Feng, Roger <roger.feng@...>
Subject: RE: [PATCH v5] IntelSiliconPkg/VTd: Add iommu 5 level paging support

Reviewed-by: Jenny Huang < jenny.huang@...>

-----Original Message-----
From: Sheng, W <w.sheng@...>
Sent: Tuesday, December 1, 2020 7:03 PM
To: Yao, Jiewen <jiewen.yao@...>; devel@edk2.groups.io
Cc: Ni, Ray <ray.ni@...>; Chaganty, Rangasai V
<rangasai.v.chaganty@...>; Huang, Jenny <jenny.huang@...>;
Feng, Roger <roger.feng@...>
Subject: [PATCH v5] IntelSiliconPkg/VTd: Add iommu 5 level paging support

Hi Jiewen,
About the patch of support 5 level paging iommu.
Thank you for giving the review comments.
I have done all the update.
Could you give "review by" on this patch ?
Thank you.
BR
Sheng Wei


-----Original Message-----
From: Sheng, W
Sent: 2020年11月24日 13:44
To: Yao, Jiewen <jiewen.yao@...>; devel@edk2.groups.io
Cc: Ni, Ray <ray.ni@...>; Chaganty, Rangasai V
<rangasai.v.chaganty@...>; Huang, Jenny <jenny.huang@...>
Subject: RE: [PATCH v4] IntelSiliconPkg/VTd: Add iommu 5 level paging
support

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,
,posteri
d%3A2558558,20,2,0,78471874
Could we continue the patch review ?
BR
Sheng Wei

-----Original Message-----
From: Yao, Jiewen <jiewen.yao@...>
Sent: 2020年11月23日 16:44
To: Sheng, W <w.sheng@...>; devel@edk2.groups.io
Cc: Ni, Ray <ray.ni@...>; Chaganty, Rangasai V
<rangasai.v.chaganty@...>; Huang, Jenny
<jenny.huang@...>
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@...>
Sent: Monday, November 23, 2020 4:04 PM
To: devel@edk2.groups.io
Cc: Ni, Ray <ray.ni@...>; Chaganty, Rangasai V
<rangasai.v.chaganty@...>; Yao, Jiewen
<jiewen.yao@...>; Huang, Jenny <jenny.huang@...>
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@...>
Cc: Ray Ni <ray.ni@...>
Cc: Rangasai V Chaganty <rangasai.v.chaganty@...>
Cc: Jiewen Yao <jiewen.yao@...>
Cc: Jenny Huang <jenny.huang@...>
---
.../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/Translatio
nT
ab
le.c
b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/Translatio
nT
ab
le.c
index 201d663d..6c786b40 100644
---
a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/Translatio
nT
ab
le.c
+++
b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/Translatio
nT ab 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.SecondLevelP
ag
e
TranslationPointerLo,
ContextEntry[Index2].Bits.SecondLevelPageTranslationPointerHi));
+ DumpSecondLevelPagingEntry ((VOID
*)(UINTN)VTD_64BITS_ADDRESS(ContextEntry[Index2].Bits.SecondLevelP
ag
e
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.SecondLev
el
Pa
geTranslationPointerLo,
ExtContextEntry[Index2].Bits.SecondLevelPageTranslationPointerHi))
;
+ DumpSecondLevelPagingEntry ((VOID
*)(UINTN)VTD_64BITS_ADDRESS(ExtContextEntry[Index2].Bits.SecondLev
el
Pa
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