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