public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Yao, Jiewen" <jiewen.yao@intel.com>
To: "Zeng, Star" <star.zeng@intel.com>,
	"edk2-devel@lists.01.org" <edk2-devel@lists.01.org>
Subject: Re: [PATCH V2 2/2] IntelSiliconPkg/IntelVTdDxe: Improve performance.
Date: Mon, 14 Aug 2017 04:16:28 +0000	[thread overview]
Message-ID: <74D8A39837DF1E4DA445A8C0B3885C503A990951@shsmsx102.ccr.corp.intel.com> (raw)
In-Reply-To: <0C09AFA07DD0434D9E2A0C6AEB0483103B918992@shsmsx102.ccr.corp.intel.com>

Thanks. I will update that.

> -----Original Message-----
> From: Zeng, Star
> Sent: Monday, August 14, 2017 11:53 AM
> To: Yao, Jiewen <jiewen.yao@intel.com>; edk2-devel@lists.01.org
> Cc: Zeng, Star <star.zeng@intel.com>
> Subject: RE: [PATCH V2 2/2] IntelSiliconPkg/IntelVTdDxe: Improve performance.
> 
> Two minor comments, others are good to me. Reviewed-by: Star Zeng
> <star.zeng@intel.com>
> 
> 1. In commit log, add WriteBackDataCacheRange() and remove duplicated "to"?
> CLFLUSH is used to to only flush the context table or second level page table if
> they are changed.
> ->
> CLFLUSH by WriteBackDataCacheRange() is used to only flush the context table
> or second level page table if they are changed.
> 
> 2. PERF_CODE can be used.
> 
>   PERF_CODE_BEGIN();
>     AsciiSPrint (PerfToken, sizeof(PerfToken),
> "VTD(S%04x.B%02x.D%02x.F%02x)", Segment, SourceId.Bits.Bus,
> SourceId.Bits.Device, SourceId.Bits.Function);
>     PERF_START (gImageHandle, PerfToken, "IntelVTD", 0);
>   PERF_CODE_END();
> 
> ->
> 
>   PERF_CODE (
>     AsciiSPrint (PerfToken, sizeof(PerfToken),
> "VTD(S%04x.B%02x.D%02x.F%02x)", Segment, SourceId.Bits.Bus,
> SourceId.Bits.Device, SourceId.Bits.Function);
>     PERF_START (gImageHandle, PerfToken, "IntelVTD", 0);
>   );
> 
> 
> Thanks,
> Star
> -----Original Message-----
> From: Yao, Jiewen
> Sent: Friday, August 11, 2017 10:54 PM
> To: edk2-devel@lists.01.org
> Cc: Zeng, Star <star.zeng@intel.com>
> Subject: [PATCH V2 2/2] IntelSiliconPkg/IntelVTdDxe: Improve performance.
> 
> This patch is to improve IOMMU performance.
> All WBINVD is removed due to performance issue.
> CLFLUSH is used to to only flush the context table or second level page table if
> they are changed.
> 
> This patch also removed some unused functions.
> 
> Cc: Star Zeng <star.zeng@intel.com>
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
> ---
>  IntelSiliconPkg/IntelVTdDxe/DmaProtection.h      |  57 ++---
>  IntelSiliconPkg/IntelVTdDxe/IntelVTdDxe.c        |  10 +
>  IntelSiliconPkg/IntelVTdDxe/IntelVTdDxe.inf      |   3 +
>  IntelSiliconPkg/IntelVTdDxe/PciInfo.c            |  12 +
>  IntelSiliconPkg/IntelVTdDxe/TranslationTable.c   |  58 ++++-
>  IntelSiliconPkg/IntelVTdDxe/TranslationTableEx.c |   2 +
>  IntelSiliconPkg/IntelVTdDxe/VtdReg.c             | 260 +++++++-------------
>  7 files changed, 186 insertions(+), 216 deletions(-)
> 
> diff --git a/IntelSiliconPkg/IntelVTdDxe/DmaProtection.h
> b/IntelSiliconPkg/IntelVTdDxe/DmaProtection.h
> index 8cfa69c..c3b57a0 100644
> --- a/IntelSiliconPkg/IntelVTdDxe/DmaProtection.h
> +++ b/IntelSiliconPkg/IntelVTdDxe/DmaProtection.h
> @@ -25,6 +25,9 @@
>  #include <Library/PciSegmentLib.h>
>  #include <Library/DebugLib.h>
>  #include <Library/UefiLib.h>
> +#include <Library/CacheMaintenanceLib.h> #include
> +<Library/PerformanceLib.h> #include <Library/PrintLib.h>
> 
>  #include <Guid/EventGroup.h>
>  #include <Guid/Acpi.h>
> @@ -58,6 +61,8 @@ typedef struct {
>    UINTN                  PciDescriptorMaxNumber;
>    BOOLEAN                *IsRealPciDevice;
>    VTD_SOURCE_ID          *PciDescriptors;
> +  // for statistic analysis
> +  UINTN                  *AccessCount;
>  } PCI_DEVICE_INFORMATION;
> 
>  typedef struct {
> @@ -68,6 +73,7 @@ typedef struct {
>    VTD_ROOT_ENTRY                   *RootEntryTable;
>    VTD_EXT_ROOT_ENTRY               *ExtRootEntryTable;
>    VTD_SECOND_LEVEL_PAGING_ENTRY    *FixedSecondLevelPagingEntry;
> +  BOOLEAN                          HasDirtyContext;
>    BOOLEAN                          HasDirtyPages;
>    PCI_DEVICE_INFORMATION           PciDeviceInfo;
>  } VTD_UNIT_INFORMATION;
> @@ -125,40 +131,6 @@ DisableDmar (
>    );
> 
>  /**
> -  Invalid VTd IOTLB page.
> -
> -  @param[in]  VtdIndex              The index of VTd engine.
> -  @param[in]  Address               The address of IOTLB page.
> -  @param[in]  AddressMode           The address mode of IOTLB page.
> -  @param[in]  DomainIdentifier      The domain ID of the source.
> -
> -  @retval EFI_SUCCESS           VTd IOTLB page is invalidated.
> -  @retval EFI_DEVICE_ERROR      VTd IOTLB page is not invalidated.
> -**/
> -EFI_STATUS
> -InvalidateVtdIOTLBPage (
> -  IN UINTN  VtdIndex,
> -  IN UINT64 Address,
> -  IN UINT8  AddressMode,
> -  IN UINT16 DomainIdentifier
> -  );
> -
> -/**
> -  Invalid VTd IOTLB domain.
> -
> -  @param[in]  VtdIndex              The index of VTd engine.
> -  @param[in]  DomainIdentifier      The domain ID of the source.
> -
> -  @retval EFI_SUCCESS           VTd IOTLB domain is invalidated.
> -  @retval EFI_DEVICE_ERROR      VTd IOTLB domain is not invalidated.
> -**/
> -EFI_STATUS
> -InvalidateVtdIOTLBDomain (
> -  IN UINTN  VtdIndex,
> -  IN UINT16 DomainIdentifier
> -  );
> -
> -/**
>    Invalid VTd global IOTLB.
> 
>    @param[in]  VtdIndex              The index of VTd engine.
> @@ -362,6 +334,7 @@ DumpSecondLevelPagingEntry (  EFI_STATUS
> SetPageAttribute (
>    IN UINTN                         VtdIndex,
> +  IN UINT16                        DomainIdentifier,
>    IN VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry,
>    IN UINT64                        BaseAddress,
>    IN UINT64                        Length,
> @@ -500,4 +473,20 @@ AllocateZeroPages (
>    IN UINTN  Pages
>    );
> 
> +/**
> +  Flush VTD page table and context table memory.
> +
> +  This action is to make sure the IOMMU engine can get final data in memory.
> +
> +  @param[in]  VtdIndex          The index used to identify a VTd engine.
> +  @param[in]  Base              The base address of memory to be
> flushed.
> +  @param[in]  Size              The size of memory in bytes to be flushed.
> +**/
> +VOID
> +FlushPageTableMemory (
> +  IN UINTN  VtdIndex,
> +  IN UINTN  Base,
> +  IN UINTN  Size
> +  );
> +
>  #endif
> diff --git a/IntelSiliconPkg/IntelVTdDxe/IntelVTdDxe.c
> b/IntelSiliconPkg/IntelVTdDxe/IntelVTdDxe.c
> index d22222d..7feaaf5 100644
> --- a/IntelSiliconPkg/IntelVTdDxe/IntelVTdDxe.c
> +++ b/IntelSiliconPkg/IntelVTdDxe/IntelVTdDxe.c
> @@ -227,6 +227,7 @@ VTdSetAttribute (
>    EFI_STATUS           Status;
>    UINT16               Segment;
>    VTD_SOURCE_ID        SourceId;
> +  CHAR8                PerfToken[sizeof("VTD(S0000.B00.D00.F00)")];
> 
>    DumpVtdIfError ();
> 
> @@ -239,8 +240,17 @@ VTdSetAttribute (
>    DEBUG ((DEBUG_VERBOSE, "PCI(S%x.B%x.D%x.F%x) ", Segment,
> SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.Function));
>    DEBUG ((DEBUG_VERBOSE, "(0x%lx~0x%lx) - %lx\n", DeviceAddress, Length,
> IoMmuAccess));
> 
> +  PERF_CODE_BEGIN();
> +    AsciiSPrint (PerfToken, sizeof(PerfToken),
> "VTD(S%04x.B%02x.D%02x.F%02x)", Segment, SourceId.Bits.Bus,
> SourceId.Bits.Device, SourceId.Bits.Function);
> +    PERF_START (gImageHandle, PerfToken, "IntelVTD", 0);
> + PERF_CODE_END();
> +
>    Status = SetAccessAttribute (Segment, SourceId, DeviceAddress, Length,
> IoMmuAccess);
> 
> +  PERF_CODE_BEGIN();
> +    PERF_END (gImageHandle, PerfToken, "IntelVTD", 0);
> + PERF_CODE_END();
> +
>    return Status;
>  }
> 
> diff --git a/IntelSiliconPkg/IntelVTdDxe/IntelVTdDxe.inf
> b/IntelSiliconPkg/IntelVTdDxe/IntelVTdDxe.inf
> index 6a61c13..697932e 100644
> --- a/IntelSiliconPkg/IntelVTdDxe/IntelVTdDxe.inf
> +++ b/IntelSiliconPkg/IntelVTdDxe/IntelVTdDxe.inf
> @@ -57,6 +57,9 @@
>    BaseMemoryLib
>    MemoryAllocationLib
>    UefiLib
> +  CacheMaintenanceLib
> +  PerformanceLib
> +  PrintLib
> 
>  [Guids]
>    gEfiEventExitBootServicesGuid   ## CONSUMES ## Event
> diff --git a/IntelSiliconPkg/IntelVTdDxe/PciInfo.c
> b/IntelSiliconPkg/IntelVTdDxe/PciInfo.c
> index d5f096f..27e253d 100644
> --- a/IntelSiliconPkg/IntelVTdDxe/PciInfo.c
> +++ b/IntelSiliconPkg/IntelVTdDxe/PciInfo.c
> @@ -77,6 +77,7 @@ RegisterPciDevice (
>    UINTN                   Index;
>    BOOLEAN                 *NewIsRealPciDevice;
>    VTD_SOURCE_ID           *NewPciDescriptors;
> +  UINTN                   *NewAccessCount;
> 
>    PciDeviceInfo = &mVtdUnitInformation[VtdIndex].PciDeviceInfo;
> 
> @@ -112,6 +113,12 @@ RegisterPciDevice (
>          FreePool (NewIsRealPciDevice);
>          return EFI_OUT_OF_RESOURCES;
>        }
> +      NewAccessCount = AllocateZeroPool (sizeof(*NewAccessCount) *
> (PciDeviceInfo->PciDescriptorMaxNumber + MAX_PCI_DESCRIPTORS));
> +      if (NewAccessCount == NULL) {
> +        FreePool (NewIsRealPciDevice);
> +        FreePool (NewPciDescriptors);
> +        return EFI_OUT_OF_RESOURCES;
> +      }
>        PciDeviceInfo->PciDescriptorMaxNumber += MAX_PCI_DESCRIPTORS;
>        if (PciDeviceInfo->IsRealPciDevice != NULL) {
>          CopyMem (NewIsRealPciDevice, PciDeviceInfo->IsRealPciDevice,
> sizeof(*NewIsRealPciDevice) * PciDeviceInfo->PciDescriptorNumber);
> @@ -123,6 +130,11 @@ RegisterPciDevice (
>          FreePool (PciDeviceInfo->PciDescriptors);
>        }
>        PciDeviceInfo->PciDescriptors = NewPciDescriptors;
> +      if (PciDeviceInfo->AccessCount != NULL) {
> +        CopyMem (NewAccessCount, PciDeviceInfo->AccessCount,
> sizeof(*NewAccessCount) * PciDeviceInfo->PciDescriptorNumber);
> +        FreePool (PciDeviceInfo->AccessCount);
> +      }
> +      PciDeviceInfo->AccessCount = NewAccessCount;
>      }
> 
>      ASSERT (PciDeviceInfo->PciDescriptorNumber <
> PciDeviceInfo->PciDescriptorMaxNumber);
> diff --git a/IntelSiliconPkg/IntelVTdDxe/TranslationTable.c
> b/IntelSiliconPkg/IntelVTdDxe/TranslationTable.c
> index 961d7ca..80fc823 100644
> --- a/IntelSiliconPkg/IntelVTdDxe/TranslationTable.c
> +++ b/IntelSiliconPkg/IntelVTdDxe/TranslationTable.c
> @@ -124,6 +124,7 @@ CreateContextEntry (
>        RootEntry->Bits.ContextTablePointerHi  = (UINT32) RShiftU64
> ((UINT64)(UINTN)Buffer, 32);
>        RootEntry->Bits.Present = 1;
>        Buffer = (UINT8 *)Buffer + EFI_PAGES_TO_SIZE (ContextPages);
> +      FlushPageTableMemory (VtdIndex, (UINTN)RootEntry,
> + sizeof(*RootEntry));
>      }
> 
>      ContextEntryTable = (VTD_CONTEXT_ENTRY
> *)(UINTN)VTD_64BITS_ADDRESS(RootEntry->Bits.ContextTablePointerLo,
> RootEntry->Bits.ContextTablePointerHi) ; @@ -142,6 +143,7 @@
> CreateContextEntry (
>        ContextEntry->Bits.AddressWidth = 0x2;
>        break;
>      }
> +    FlushPageTableMemory (VtdIndex, (UINTN)ContextEntry,
> + sizeof(*ContextEntry));
>    }
> 
>    return EFI_SUCCESS;
> @@ -250,8 +252,11 @@ CreateSecondLevelPagingEntryTable (
>            goto Done;
>          }
>        }
> +      FlushPageTableMemory (VtdIndex, (UINTN)Lvl2PtEntry, SIZE_4KB);
>      }
> +    FlushPageTableMemory (VtdIndex, (UINTN)&Lvl3PtEntry[Lvl3Start],
> + (UINTN)&Lvl3PtEntry[Lvl3End + 1] - (UINTN)&Lvl3PtEntry[Lvl3Start]);
>    }
> +  FlushPageTableMemory (VtdIndex, (UINTN)&Lvl4PtEntry[Lvl4Start],
> + (UINTN)&Lvl4PtEntry[Lvl4End + 1] - (UINTN)&Lvl4PtEntry[Lvl4Start]);
> 
>  Done:
>    return SecondLevelPagingEntry;
> @@ -429,9 +434,10 @@ InvalidatePageEntry (
>    IN UINTN                 VtdIndex
>    )
>  {
> -  if (mVtdUnitInformation[VtdIndex].HasDirtyPages) {
> +  if (mVtdUnitInformation[VtdIndex].HasDirtyContext ||
> + mVtdUnitInformation[VtdIndex].HasDirtyPages) {
>      InvalidateVtdIOTLBGlobal (VtdIndex);
>    }
> +  mVtdUnitInformation[VtdIndex].HasDirtyContext = FALSE;
>    mVtdUnitInformation[VtdIndex].HasDirtyPages = FALSE;  }
> 
> @@ -498,6 +504,7 @@ PageAttributeToLength (
>  /**
>    Return page table entry to match the address.
> 
> +  @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[out]  PageAttributes           The page attribute of the page
> entry.
> @@ -506,6 +513,7 @@ PageAttributeToLength (  **/  VOID *
> GetSecondLevelPageTableEntry (
> +  IN  UINTN                         VtdIndex,
>    IN  VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry,
>    IN  PHYSICAL_ADDRESS              Address,
>    OUT PAGE_ATTRIBUTE                *PageAttribute
> @@ -535,6 +543,7 @@ GetSecondLevelPageTableEntry (
>        return NULL;
>      }
>      SetSecondLevelPagingEntryAttribute
> ((VTD_SECOND_LEVEL_PAGING_ENTRY *)&L4PageTable[Index4],
> EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);
> +    FlushPageTableMemory (VtdIndex, (UINTN)&L4PageTable[Index4],
> + sizeof(L4PageTable[Index4]));
>    }
> 
>    L3PageTable = (UINT64 *)(UINTN)(L4PageTable[Index4] &
> PAGING_4K_ADDRESS_MASK_64); @@ -547,6 +556,7 @@
> GetSecondLevelPageTableEntry (
>        return NULL;
>      }
>      SetSecondLevelPagingEntryAttribute
> ((VTD_SECOND_LEVEL_PAGING_ENTRY *)&L3PageTable[Index3],
> EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);
> +    FlushPageTableMemory (VtdIndex, (UINTN)&L3PageTable[Index3],
> + sizeof(L3PageTable[Index3]));
>    }
>    if ((L3PageTable[Index3] & VTD_PG_PS) != 0) {
>      // 1G
> @@ -559,6 +569,7 @@ GetSecondLevelPageTableEntry (
>      L2PageTable[Index2] = Address & PAGING_2M_ADDRESS_MASK_64;
>      SetSecondLevelPagingEntryAttribute
> ((VTD_SECOND_LEVEL_PAGING_ENTRY *)&L2PageTable[Index2], 0);
>      L2PageTable[Index2] |= VTD_PG_PS;
> +    FlushPageTableMemory (VtdIndex, (UINTN)&L2PageTable[Index2],
> + sizeof(L2PageTable[Index2]));
>    }
>    if ((L2PageTable[Index2] & VTD_PG_PS) != 0) {
>      // 2M
> @@ -579,12 +590,14 @@ GetSecondLevelPageTableEntry (
>  /**
>    Modify memory attributes of page entry.
> 
> +  @param[in]   VtdIndex         The index used to identify a VTd engine.
>    @param[in]   PageEntry        The page entry.
>    @param[in]   IoMmuAccess      The IOMMU access.
>    @param[out]  IsModified       TRUE means page table modified. FALSE
> means page table not modified.
>  **/
>  VOID
>  ConvertSecondLevelPageEntryAttribute (
> +  IN  UINTN                             VtdIndex,
>    IN  VTD_SECOND_LEVEL_PAGING_ENTRY     *PageEntry,
>    IN  UINT64                            IoMmuAccess,
>    OUT BOOLEAN                           *IsModified
> @@ -595,6 +608,7 @@ ConvertSecondLevelPageEntryAttribute (
> 
>    CurrentPageEntry = PageEntry->Uint64;
>    SetSecondLevelPagingEntryAttribute (PageEntry, IoMmuAccess);
> +  FlushPageTableMemory (VtdIndex, (UINTN)PageEntry,
> + sizeof(*PageEntry));
>    NewPageEntry = PageEntry->Uint64;
>    if (CurrentPageEntry != NewPageEntry) {
>      *IsModified = TRUE;
> @@ -639,6 +653,7 @@ NeedSplitPage (
>  /**
>    This function splits one page entry to small page entries.
> 
> +  @param[in]  VtdIndex         The index used to identify a VTd engine.
>    @param[in]  PageEntry        The page entry to be splitted.
>    @param[in]  PageAttribute    The page attribute of the page entry.
>    @param[in]  SplitAttribute   How to split the page entry.
> @@ -649,6 +664,7 @@ NeedSplitPage (
>  **/
>  RETURN_STATUS
>  SplitSecondLevelPage (
> +  IN  UINTN                             VtdIndex,
>    IN  VTD_SECOND_LEVEL_PAGING_ENTRY     *PageEntry,
>    IN  PAGE_ATTRIBUTE                    PageAttribute,
>    IN  PAGE_ATTRIBUTE                    SplitAttribute
> @@ -675,8 +691,11 @@ SplitSecondLevelPage (
>        for (Index = 0; Index < SIZE_4KB / sizeof(UINT64); Index++) {
>          NewPageEntry[Index] = (BaseAddress + SIZE_4KB * Index) |
> (PageEntry->Uint64 & PAGE_PROGATE_BITS);
>        }
> +      FlushPageTableMemory (VtdIndex, (UINTN)NewPageEntry, SIZE_4KB);
> +
>        PageEntry->Uint64 = (UINT64)(UINTN)NewPageEntry;
>        SetSecondLevelPagingEntryAttribute (PageEntry,
> EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);
> +      FlushPageTableMemory (VtdIndex, (UINTN)PageEntry,
> + sizeof(*PageEntry));
>        return RETURN_SUCCESS;
>      } else {
>        return RETURN_UNSUPPORTED;
> @@ -697,8 +716,11 @@ SplitSecondLevelPage (
>        for (Index = 0; Index < SIZE_4KB / sizeof(UINT64); Index++) {
>          NewPageEntry[Index] = (BaseAddress + SIZE_2MB * Index) |
> VTD_PG_PS | (PageEntry->Uint64 & PAGE_PROGATE_BITS);
>        }
> +      FlushPageTableMemory (VtdIndex, (UINTN)NewPageEntry, SIZE_4KB);
> +
>        PageEntry->Uint64 = (UINT64)(UINTN)NewPageEntry;
>        SetSecondLevelPagingEntryAttribute (PageEntry,
> EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);
> +      FlushPageTableMemory (VtdIndex, (UINTN)PageEntry,
> + sizeof(*PageEntry));
>        return RETURN_SUCCESS;
>      } else {
>        return RETURN_UNSUPPORTED;
> @@ -730,6 +752,7 @@ SplitSecondLevelPage (  EFI_STATUS
> SetSecondLevelPagingAttribute (
>    IN UINTN                         VtdIndex,
> +  IN UINT16                        DomainIdentifier,
>    IN VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry,
>    IN UINT64                        BaseAddress,
>    IN UINT64                        Length,
> @@ -756,7 +779,7 @@ SetSecondLevelPagingAttribute (
>    }
> 
>    while (Length != 0) {
> -    PageEntry = GetSecondLevelPageTableEntry (SecondLevelPagingEntry,
> BaseAddress, &PageAttribute);
> +    PageEntry = GetSecondLevelPageTableEntry (VtdIndex,
> + SecondLevelPagingEntry, BaseAddress, &PageAttribute);
>      if (PageEntry == NULL) {
>        DEBUG ((DEBUG_ERROR, "PageEntry - NULL\n"));
>        return RETURN_UNSUPPORTED;
> @@ -764,7 +787,7 @@ SetSecondLevelPagingAttribute (
>      PageEntryLength = PageAttributeToLength (PageAttribute);
>      SplitAttribute = NeedSplitPage (BaseAddress, Length, PageAttribute);
>      if (SplitAttribute == PageNone) {
> -      ConvertSecondLevelPageEntryAttribute (PageEntry, IoMmuAccess,
> &IsEntryModified);
> +      ConvertSecondLevelPageEntryAttribute (VtdIndex, PageEntry,
> + IoMmuAccess, &IsEntryModified);
>        if (IsEntryModified) {
>          mVtdUnitInformation[VtdIndex].HasDirtyPages = TRUE;
>        }
> @@ -774,7 +797,7 @@ SetSecondLevelPagingAttribute (
>        BaseAddress += PageEntryLength;
>        Length -= PageEntryLength;
>      } else {
> -      Status = SplitSecondLevelPage (PageEntry, PageAttribute, SplitAttribute);
> +      Status = SplitSecondLevelPage (VtdIndex, PageEntry,
> + PageAttribute, SplitAttribute);
>        if (RETURN_ERROR (Status)) {
>          DEBUG ((DEBUG_ERROR, "SplitSecondLevelPage - %r\n", Status));
>          return RETURN_UNSUPPORTED;
> @@ -787,8 +810,6 @@ SetSecondLevelPagingAttribute (
>      }
>    }
> 
> -  InvalidatePageEntry (VtdIndex);
> -
>    return EFI_SUCCESS;
>  }
> 
> @@ -814,6 +835,7 @@ SetSecondLevelPagingAttribute (  EFI_STATUS
> SetPageAttribute (
>    IN UINTN                         VtdIndex,
> +  IN UINT16                        DomainIdentifier,
>    IN VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry,
>    IN UINT64                        BaseAddress,
>    IN UINT64                        Length,
> @@ -823,7 +845,7 @@ SetPageAttribute (
>    EFI_STATUS Status;
>    Status = EFI_NOT_FOUND;
>    if (SecondLevelPagingEntry != NULL) {
> -    Status = SetSecondLevelPagingAttribute (VtdIndex,
> SecondLevelPagingEntry, BaseAddress, Length, IoMmuAccess);
> +    Status = SetSecondLevelPagingAttribute (VtdIndex, DomainIdentifier,
> + SecondLevelPagingEntry, BaseAddress, Length, IoMmuAccess);
>    }
>    return Status;
>  }
> @@ -862,6 +884,8 @@ SetAccessAttribute (
>    VTD_CONTEXT_ENTRY             *ContextEntry;
>    VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry;
>    UINT64                        Pt;
> +  UINTN                         PciDescriptorIndex;
> +  UINT16                        DomainIdentifier;
> 
>    SecondLevelPagingEntry = NULL;
> 
> @@ -873,6 +897,13 @@ SetAccessAttribute (
>      return EFI_DEVICE_ERROR;
>    }
> 
> +  PciDescriptorIndex = GetPciDescriptor (VtdIndex, Segment, SourceId);
> + mVtdUnitInformation[VtdIndex].PciDeviceInfo.AccessCount[PciDescriptorI
> + ndex]++;
> +  //
> +  // DomainId should not be 0.
> +  //
> +  DomainIdentifier = (UINT16)(PciDescriptorIndex + 1);
> +
>    if (ExtContextEntry != NULL) {
>      if (ExtContextEntry->Bits.Present == 0) {
>        SecondLevelPagingEntry = CreateSecondLevelPagingEntry (VtdIndex, 0);
> @@ -881,9 +912,11 @@ SetAccessAttribute (
> 
>        ExtContextEntry->Bits.SecondLevelPageTranslationPointerLo = (UINT32)
> Pt;
>        ExtContextEntry->Bits.SecondLevelPageTranslationPointerHi = (UINT32)
> RShiftU64(Pt, 20);
> -      ExtContextEntry->Bits.DomainIdentifier = (UINT16) GetPciDescriptor
> (VtdIndex, Segment, SourceId);
> +      ExtContextEntry->Bits.DomainIdentifier = DomainIdentifier;
>        ExtContextEntry->Bits.Present = 1;
> +      FlushPageTableMemory (VtdIndex, (UINTN)ExtContextEntry,
> + sizeof(*ExtContextEntry));
>        DumpDmarExtContextEntryTable
> (mVtdUnitInformation[VtdIndex].ExtRootEntryTable);
> +      mVtdUnitInformation[VtdIndex].HasDirtyContext = TRUE;
>      } else {
>        SecondLevelPagingEntry = (VOID
> *)(UINTN)VTD_64BITS_ADDRESS(ExtContextEntry->Bits.SecondLevelPageTransla
> tionPointerLo, ExtContextEntry->Bits.SecondLevelPageTranslationPointerHi);
>        DEBUG ((DEBUG_VERBOSE,"SecondLevelPagingEntry - 0x%x (S%04x
> B%02x D%02x F%02x)\n", SecondLevelPagingEntry, Segment, SourceId.Bits.Bus,
> SourceId.Bits.Device, SourceId.Bits.Function)); @@ -896,9 +929,11 @@
> SetAccessAttribute (
> 
>        ContextEntry->Bits.SecondLevelPageTranslationPointerLo = (UINT32) Pt;
>        ContextEntry->Bits.SecondLevelPageTranslationPointerHi = (UINT32)
> RShiftU64(Pt, 20);
> -      ContextEntry->Bits.DomainIdentifier = (UINT16) GetPciDescriptor
> (VtdIndex, Segment, SourceId);
> +      ContextEntry->Bits.DomainIdentifier = DomainIdentifier;
>        ContextEntry->Bits.Present = 1;
> +      FlushPageTableMemory (VtdIndex, (UINTN)ContextEntry,
> + sizeof(*ContextEntry));
>        DumpDmarContextEntryTable
> (mVtdUnitInformation[VtdIndex].RootEntryTable);
> +      mVtdUnitInformation[VtdIndex].HasDirtyContext = TRUE;
>      } else {
>        SecondLevelPagingEntry = (VOID
> *)(UINTN)VTD_64BITS_ADDRESS(ContextEntry->Bits.SecondLevelPageTranslatio
> nPointerLo, ContextEntry->Bits.SecondLevelPageTranslationPointerHi);
>        DEBUG ((DEBUG_VERBOSE,"SecondLevelPagingEntry - 0x%x (S%04x
> B%02x D%02x F%02x)\n", SecondLevelPagingEntry, Segment, SourceId.Bits.Bus,
> SourceId.Bits.Device, SourceId.Bits.Function)); @@ -911,6 +946,7 @@
> SetAccessAttribute (
>    if (SecondLevelPagingEntry !=
> mVtdUnitInformation[VtdIndex].FixedSecondLevelPagingEntry) {
>      Status = SetPageAttribute (
>                 VtdIndex,
> +               DomainIdentifier,
>                 SecondLevelPagingEntry,
>                 BaseAddress,
>                 Length,
> @@ -922,6 +958,8 @@ SetAccessAttribute (
>      }
>    }
> 
> +  InvalidatePageEntry (VtdIndex);
> +
>    return EFI_SUCCESS;
>  }
> 
> @@ -965,11 +1003,13 @@ AlwaysEnablePageAttribute (
>      ExtContextEntry->Bits.SecondLevelPageTranslationPointerHi = (UINT32)
> RShiftU64(Pt, 20);
>      ExtContextEntry->Bits.DomainIdentifier = ((1 <<
> (UINT8)((UINTN)mVtdUnitInformation[VtdIndex].CapReg.Bits.ND * 2 + 4)) - 1);
>      ExtContextEntry->Bits.Present = 1;
> +    FlushPageTableMemory (VtdIndex, (UINTN)ExtContextEntry,
> + sizeof(*ExtContextEntry));
>    } else if (ContextEntry != NULL) {
>      ContextEntry->Bits.SecondLevelPageTranslationPointerLo = (UINT32) Pt;
>      ContextEntry->Bits.SecondLevelPageTranslationPointerHi = (UINT32)
> RShiftU64(Pt, 20);
>      ContextEntry->Bits.DomainIdentifier = ((1 <<
> (UINT8)((UINTN)mVtdUnitInformation[VtdIndex].CapReg.Bits.ND * 2 + 4)) - 1);
>      ContextEntry->Bits.Present = 1;
> +    FlushPageTableMemory (VtdIndex, (UINTN)ContextEntry,
> + sizeof(*ContextEntry));
>    }
> 
>    return EFI_SUCCESS;
> diff --git a/IntelSiliconPkg/IntelVTdDxe/TranslationTableEx.c
> b/IntelSiliconPkg/IntelVTdDxe/TranslationTableEx.c
> index 65ed16e..9d4e6ea 100644
> --- a/IntelSiliconPkg/IntelVTdDxe/TranslationTableEx.c
> +++ b/IntelSiliconPkg/IntelVTdDxe/TranslationTableEx.c
> @@ -73,6 +73,7 @@ CreateExtContextEntry (
>        ExtRootEntry->Bits.UpperContextTablePointerLo  = (UINT32) RShiftU64
> ((UINT64)(UINTN)Buffer, 12) + 1;
>        ExtRootEntry->Bits.UpperContextTablePointerHi  = (UINT32) RShiftU64
> (RShiftU64 ((UINT64)(UINTN)Buffer, 12) + 1, 20);
>        ExtRootEntry->Bits.UpperPresent = 1;
> +      FlushPageTableMemory (VtdIndex, (UINTN)ExtRootEntry,
> + sizeof(*ExtRootEntry));
>        Buffer = (UINT8 *)Buffer + EFI_PAGES_TO_SIZE (ContextPages);
>      }
> 
> @@ -92,6 +93,7 @@ CreateExtContextEntry (
>        ExtContextEntry->Bits.AddressWidth = 0x2;
>        break;
>      }
> +    FlushPageTableMemory (VtdIndex, (UINTN)ExtContextEntry,
> + sizeof(*ExtContextEntry));
>    }
> 
>    return EFI_SUCCESS;
> diff --git a/IntelSiliconPkg/IntelVTdDxe/VtdReg.c
> b/IntelSiliconPkg/IntelVTdDxe/VtdReg.c
> index f36e3de..b1178b7 100644
> --- a/IntelSiliconPkg/IntelVTdDxe/VtdReg.c
> +++ b/IntelSiliconPkg/IntelVTdDxe/VtdReg.c
> @@ -20,43 +20,62 @@ VTD_UNIT_INFORMATION
> *mVtdUnitInformation;
>  BOOLEAN  mVtdEnabled;
> 
>  /**
> -  Invalid VTd global IOTLB.
> +  Flush VTD page table and context table memory.
> 
> -  @param[in]  VtdIndex              The index of VTd engine.
> +  This action is to make sure the IOMMU engine can get final data in memory.
> 
> -  @retval EFI_SUCCESS           VTd global IOTLB is invalidated.
> -  @retval EFI_DEVICE_ERROR      VTd global IOTLB is not invalidated.
> +  @param[in]  VtdIndex          The index used to identify a VTd engine.
> +  @param[in]  Base              The base address of memory to be
> flushed.
> +  @param[in]  Size              The size of memory in bytes to be flushed.
>  **/
> -EFI_STATUS
> -InvalidateVtdIOTLBGlobal (
> +VOID
> +FlushPageTableMemory (
> +  IN UINTN  VtdIndex,
> +  IN UINTN  Base,
> +  IN UINTN  Size
> +  )
> +{
> +  if (mVtdUnitInformation[VtdIndex].ECapReg.Bits.C == 0) {
> +    WriteBackDataCacheRange ((VOID *)Base, Size);
> +  }
> +}
> +
> +/**
> +  Flush VTd engine write buffer.
> +
> +  @param[in]  VtdIndex          The index used to identify a VTd engine.
> +**/
> +VOID
> +FlushWriteBuffer (
>    IN UINTN  VtdIndex
>    )
>  {
> -  UINT64  Reg64;
>    UINT32  Reg32;
> 
> -  if (!mVtdEnabled) {
> -    return EFI_SUCCESS;
> +  if (mVtdUnitInformation[VtdIndex].CapReg.Bits.RWBF != 0) {
> +    Reg32 = MmioRead32
> (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_GSTS_REG);
> +    MmioWrite32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress +
> R_GCMD_REG, Reg32 | B_GMCD_REG_WBF);
> +    do {
> +      Reg32 = MmioRead32
> (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_GSTS_REG);
> +    } while ((Reg32 & B_GSTS_REG_WBF) != 0);
>    }
> +}
> 
> -  DEBUG((DEBUG_VERBOSE, "InvalidateVtdIOTLBGlobal(%d)\n", VtdIndex));
> -
> -  AsmWbinvd();
> +/**
> +  Invalidate VTd context cache.
> 
> -  //
> -  // Write Buffer Flush before invalidation
> -  //
> -  Reg32 = MmioRead32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress
> + R_CAP_REG);
> -  if ((Reg32 & B_CAP_REG_RWBF) != 0) {
> -    MmioWrite32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress +
> R_GCMD_REG, B_GMCD_REG_WBF);
> -  }
> +  @param[in]  VtdIndex          The index used to identify a VTd engine.
> +**/
> +EFI_STATUS
> +InvalidateContextCache (
> +  IN UINTN  VtdIndex
> +  )
> +{
> +  UINT64  Reg64;
> 
> -  //
> -  // Invalidate the context cache
> -  //
>    Reg64 = MmioRead64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress
> + R_CCMD_REG);
>    if ((Reg64 & B_CCMD_REG_ICC) != 0) {
> -    DEBUG ((DEBUG_ERROR,"ERROR: InvalidateVtdIOTLBGlobal:
> B_CCMD_REG_ICC is set for VTD(%d)\n",VtdIndex));
> +    DEBUG ((DEBUG_ERROR,"ERROR: InvalidateContextCache:
> B_CCMD_REG_ICC
> + is set for VTD(%d)\n",VtdIndex));
>      return EFI_DEVICE_ERROR;
>    }
> 
> @@ -68,97 +87,29 @@ InvalidateVtdIOTLBGlobal (
>      Reg64 = MmioRead64
> (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_CCMD_REG);
>    } while ((Reg64 & B_CCMD_REG_ICC) != 0);
> 
> -  //
> -  // Invalidate the IOTLB cache
> -  //
> -
> -  Reg64 = MmioRead64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress
> + (mVtdUnitInformation[VtdIndex].ECapReg.Bits.IRO * 16) + R_IOTLB_REG);
> -  if ((Reg64 & B_IOTLB_REG_IVT) != 0) {
> -    DEBUG ((DEBUG_ERROR,"ERROR: InvalidateVtdIOTLBGlobal:
> B_IOTLB_REG_IVT is set for VTD(%d)\n", VtdIndex));
> -    return EFI_DEVICE_ERROR;
> -  }
> -
> -  Reg64 &= ((~B_IOTLB_REG_IVT) & (~B_IOTLB_REG_IIRG_MASK));
> -  Reg64 |= (B_IOTLB_REG_IVT | V_IOTLB_REG_IIRG_GLOBAL);
> -  MmioWrite64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress +
> (mVtdUnitInformation[VtdIndex].ECapReg.Bits.IRO * 16) + R_IOTLB_REG,
> Reg64);
> -
> -  do {
> -    Reg64 = MmioRead64
> (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress +
> (mVtdUnitInformation[VtdIndex].ECapReg.Bits.IRO * 16) + R_IOTLB_REG);
> -  } while ((Reg64 & B_IOTLB_REG_IVT) != 0);
> -
> -  //
> -  // Disable VTd
> -  //
> -  MmioWrite32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress +
> R_GCMD_REG, B_GMCD_REG_SRTP);
> -  do {
> -    Reg32 = MmioRead32
> (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_GSTS_REG);
> -  } while((Reg32 & B_GSTS_REG_RTPS) == 0);
> -
> -  //
> -  // Enable VTd
> -  //
> -  MmioWrite32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress +
> R_GCMD_REG, B_GMCD_REG_TE);
> -  do {
> -    Reg32 = MmioRead32
> (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_GSTS_REG);
> -  } while ((Reg32 & B_GSTS_REG_TE) == 0);
> -
>    return EFI_SUCCESS;
>  }
> 
>  /**
> -  Invalid VTd IOTLB domain.
> -
> -  @param[in]  VtdIndex              The index of VTd engine.
> -  @param[in]  DomainIdentifier      The domain ID of the source.
> +  Invalidate VTd IOTLB.
> 
> -  @retval EFI_SUCCESS           VTd IOTLB domain is invalidated.
> -  @retval EFI_DEVICE_ERROR      VTd IOTLB domain is not invalidated.
> +  @param[in]  VtdIndex          The index used to identify a VTd engine.
>  **/
>  EFI_STATUS
> -InvalidateVtdIOTLBDomain (
> -  IN UINTN  VtdIndex,
> -  IN UINT16 DomainIdentifier
> +InvalidateIOTLB (
> +  IN UINTN  VtdIndex
>    )
>  {
>    UINT64  Reg64;
> 
> -  if (!mVtdEnabled) {
> -    return EFI_SUCCESS;
> -  }
> -
> -  DEBUG((DEBUG_VERBOSE, "InvalidateVtdIOTLBDomain(%d): 0x%016lx
> (0x%04x)\n", VtdIndex, DomainIdentifier));
> -
> -  //
> -  // Invalidate the context cache
> -  //
> -  Reg64 = MmioRead64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress
> + R_CCMD_REG);
> -  if ((Reg64 & B_CCMD_REG_ICC) != 0) {
> -    DEBUG ((DEBUG_ERROR,"ERROR: InvalidateVtdIOTLBDomain:
> B_CCMD_REG_ICC is set for VTD(%d)\n",VtdIndex));
> -    return EFI_DEVICE_ERROR;
> -  }
> -
> -  Reg64 &= ((~B_CCMD_REG_ICC) & (~B_CCMD_REG_CIRG_MASK));
> -  Reg64 |= (B_CCMD_REG_ICC | V_CCMD_REG_CIRG_DOMAIN);
> -  Reg64 |= (B_CCMD_REG_ICC | V_CCMD_REG_CIRG_DOMAIN);
> -  MmioWrite64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress +
> R_CCMD_REG, Reg64);
> -
> -  do {
> -    Reg64 = MmioRead64
> (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_CCMD_REG);
> -  } while ((Reg64 & B_CCMD_REG_ICC) != 0);
> -
> -  //
> -  // Invalidate the IOTLB cache
> -  //
> -
>    Reg64 = MmioRead64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress
> + (mVtdUnitInformation[VtdIndex].ECapReg.Bits.IRO * 16) + R_IOTLB_REG);
>    if ((Reg64 & B_IOTLB_REG_IVT) != 0) {
> -    DEBUG ((DEBUG_ERROR,"ERROR: InvalidateVtdIOTLBDomain:
> B_IOTLB_REG_IVT is set for VTD(%d)\n", VtdIndex));
> +    DEBUG ((DEBUG_ERROR,"ERROR: InvalidateIOTLB: B_IOTLB_REG_IVT is set
> + for VTD(%d)\n", VtdIndex));
>      return EFI_DEVICE_ERROR;
>    }
> 
>    Reg64 &= ((~B_IOTLB_REG_IVT) & (~B_IOTLB_REG_IIRG_MASK));
> -  Reg64 |= (B_IOTLB_REG_IVT | V_IOTLB_REG_IIRG_DOMAIN);
> -  Reg64 |= LShiftU64 (DomainIdentifier, 32);
> +  Reg64 |= (B_IOTLB_REG_IVT | V_IOTLB_REG_IIRG_GLOBAL);
>    MmioWrite64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress +
> (mVtdUnitInformation[VtdIndex].ECapReg.Bits.IRO * 16) + R_IOTLB_REG,
> Reg64);
> 
>    do {
> @@ -169,53 +120,41 @@ InvalidateVtdIOTLBDomain (  }
> 
>  /**
> -  Invalid VTd IOTLB page.
> +  Invalid VTd global IOTLB.
> 
>    @param[in]  VtdIndex              The index of VTd engine.
> -  @param[in]  Address               The address of IOTLB page.
> -  @param[in]  AddressMode           The address mode of IOTLB page.
> -  @param[in]  DomainIdentifier      The domain ID of the source.
> 
> -  @retval EFI_SUCCESS           VTd IOTLB page is invalidated.
> -  @retval EFI_DEVICE_ERROR      VTd IOTLB page is not invalidated.
> +  @retval EFI_SUCCESS           VTd global IOTLB is invalidated.
> +  @retval EFI_DEVICE_ERROR      VTd global IOTLB is not invalidated.
>  **/
>  EFI_STATUS
> -InvalidateVtdIOTLBPage (
> -  IN UINTN  VtdIndex,
> -  IN UINT64 Address,
> -  IN UINT8  AddressMode,
> -  IN UINT16 DomainIdentifier
> +InvalidateVtdIOTLBGlobal (
> +  IN UINTN  VtdIndex
>    )
>  {
> -  UINT64  Reg64;
> -  UINT64  Data64;
> -
>    if (!mVtdEnabled) {
>      return EFI_SUCCESS;
>    }
> 
> -  DEBUG((DEBUG_VERBOSE, "InvalidateVtdIOTLBPage(%d): 0x%016lx
> (0x%02x)\n", VtdIndex, Address, AddressMode));
> -
> -  if (mVtdUnitInformation[VtdIndex].CapReg.Bits.PSI != 0) {
> -    Reg64 = MmioRead64
> (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress +
> (mVtdUnitInformation[VtdIndex].ECapReg.Bits.IRO * 16) + R_IOTLB_REG);
> -    if ((Reg64 & B_IOTLB_REG_IVT) != 0) {
> -      DEBUG ((DEBUG_ERROR,"ERROR: InvalidateVtdIOTLBPage:
> B_IOTLB_REG_IVT is set for VTD(%d)\n", VtdIndex));
> -      return EFI_DEVICE_ERROR;
> -    }
> +  DEBUG((DEBUG_VERBOSE, "InvalidateVtdIOTLBGlobal(%d)\n", VtdIndex));
> 
> -    Data64 = Address | AddressMode;
> -    MmioWrite64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress +
> (mVtdUnitInformation[VtdIndex].ECapReg.Bits.IRO * 16) + R_IVA_REG, Data64);
> +  //
> +  // Write Buffer Flush before invalidation  //  FlushWriteBuffer
> + (VtdIndex);
> 
> -    Reg64 &= ((~B_IOTLB_REG_IVT) & (~B_IOTLB_REG_IIRG_MASK));
> -    Reg64 |= (B_IOTLB_REG_IVT | V_IOTLB_REG_IIRG_PAGE);
> -    Reg64 |= LShiftU64 (DomainIdentifier, 32);
> -    MmioWrite64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress +
> (mVtdUnitInformation[VtdIndex].ECapReg.Bits.IRO * 16) + R_IOTLB_REG,
> Reg64);
> +  //
> +  // Invalidate the context cache
> +  //
> +  if (mVtdUnitInformation[VtdIndex].HasDirtyContext) {
> +    InvalidateContextCache (VtdIndex);
> +  }
> 
> -    do {
> -      Reg64 = MmioRead64
> (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress +
> (mVtdUnitInformation[VtdIndex].ECapReg.Bits.IRO * 16) + R_IOTLB_REG);
> -    } while ((Reg64 & B_IOTLB_REG_IVT) != 0);
> -  } else {
> -    InvalidateVtdIOTLBGlobal (VtdIndex);
> +  //
> +  // Invalidate the IOTLB cache
> +  //
> +  if (mVtdUnitInformation[VtdIndex].HasDirtyContext ||
> mVtdUnitInformation[VtdIndex].HasDirtyPages) {
> +    InvalidateIOTLB (VtdIndex);
>    }
> 
>    return EFI_SUCCESS;
> @@ -268,11 +207,8 @@ EnableDmar (
>    )
>  {
>    UINTN     Index;
> -  UINT64    Reg64;
>    UINT32    Reg32;
> 
> -  AsmWbinvd();
> -
>    for (Index = 0; Index < mVtdUnitNumber; Index++) {
>      DEBUG((DEBUG_INFO, ">>>>>>EnableDmar() for engine [%d] \n", Index));
> 
> @@ -299,48 +235,17 @@ EnableDmar (
>      //
>      // Write Buffer Flush before invalidation
>      //
> -    Reg32 = MmioRead32 (mVtdUnitInformation[Index].VtdUnitBaseAddress +
> R_CAP_REG);
> -    if ((Reg32 & B_CAP_REG_RWBF) != 0) {
> -      MmioWrite32 (mVtdUnitInformation[Index].VtdUnitBaseAddress +
> R_GCMD_REG, B_GMCD_REG_WBF);
> -    }
> +    FlushWriteBuffer (Index);
> 
>      //
>      // Invalidate the context cache
>      //
> -    Reg64 = MmioRead64 (mVtdUnitInformation[Index].VtdUnitBaseAddress +
> R_CCMD_REG);
> -    if ((Reg64 & B_CCMD_REG_ICC) != 0) {
> -      DEBUG ((DEBUG_INFO,"ERROR: EnableDmar: B_CCMD_REG_ICC is set
> for VTD(%d)\n",Index));
> -      return EFI_DEVICE_ERROR;
> -    }
> -
> -    Reg64 &= ((~B_CCMD_REG_ICC) & (~B_CCMD_REG_CIRG_MASK));
> -    Reg64 |= (B_CCMD_REG_ICC | V_CCMD_REG_CIRG_GLOBAL);
> -    MmioWrite64 (mVtdUnitInformation[Index].VtdUnitBaseAddress +
> R_CCMD_REG, Reg64);
> -
> -    DEBUG((DEBUG_INFO, "EnableDmar: Waiting B_CCMD_REG_ICC ...\n"));
> -    do {
> -      Reg64 = MmioRead64 (mVtdUnitInformation[Index].VtdUnitBaseAddress
> + R_CCMD_REG);
> -    } while ((Reg64 & B_CCMD_REG_ICC) != 0);
> +    InvalidateContextCache (Index);
> 
>      //
>      // Invalidate the IOTLB cache
>      //
> -    DEBUG((DEBUG_INFO, "EnableDmar: IRO 0x%x\n",
> mVtdUnitInformation[Index].ECapReg.Bits.IRO));
> -
> -    Reg64 = MmioRead64 (mVtdUnitInformation[Index].VtdUnitBaseAddress +
> (mVtdUnitInformation[Index].ECapReg.Bits.IRO * 16) + R_IOTLB_REG);
> -    if ((Reg64 & B_IOTLB_REG_IVT) != 0) {
> -      DEBUG ((DEBUG_INFO,"ERROR: EnableDmar: B_IOTLB_REG_IVT is set for
> VTD(%d)\n", Index));
> -      return EFI_DEVICE_ERROR;
> -    }
> -
> -    Reg64 &= ((~B_IOTLB_REG_IVT) & (~B_IOTLB_REG_IIRG_MASK));
> -    Reg64 |= (B_IOTLB_REG_IVT | V_IOTLB_REG_IIRG_GLOBAL);
> -    MmioWrite64 (mVtdUnitInformation[Index].VtdUnitBaseAddress +
> (mVtdUnitInformation[Index].ECapReg.Bits.IRO * 16) + R_IOTLB_REG, Reg64);
> -
> -    DEBUG((DEBUG_INFO, "EnableDmar: Waiting B_IOTLB_REG_IVT ...\n"));
> -    do {
> -      Reg64 = MmioRead64 (mVtdUnitInformation[Index].VtdUnitBaseAddress
> + (mVtdUnitInformation[Index].ECapReg.Bits.IRO * 16) + R_IOTLB_REG);
> -    } while ((Reg64 & B_IOTLB_REG_IVT) != 0);
> +    InvalidateIOTLB (Index);
> 
>      //
>      // Enable VTd
> @@ -371,20 +276,16 @@ DisableDmar (
>    )
>  {
>    UINTN     Index;
> +  UINTN     SubIndex;
>    UINT32    Reg32;
> 
> -  AsmWbinvd();
> -
>    for (Index = 0; Index < mVtdUnitNumber; Index++) {
>      DEBUG((DEBUG_INFO, ">>>>>>DisableDmar() for engine [%d] \n",
> Index));
> 
>      //
>      // Write Buffer Flush before invalidation
>      //
> -    Reg32 = MmioRead32 (mVtdUnitInformation[Index].VtdUnitBaseAddress +
> R_CAP_REG);
> -    if ((Reg32 & B_CAP_REG_RWBF) != 0) {
> -      MmioWrite32 (mVtdUnitInformation[Index].VtdUnitBaseAddress +
> R_GCMD_REG, B_GMCD_REG_WBF);
> -    }
> +    FlushWriteBuffer (Index);
> 
>      //
>      // Disable VTd
> @@ -402,6 +303,19 @@ DisableDmar (
> 
>    mVtdEnabled = FALSE;
> 
> +  for (Index = 0; Index < mVtdUnitNumber; Index++) {
> +    DEBUG((DEBUG_INFO, "engine [%d] access\n", Index));
> +    for (SubIndex = 0; SubIndex <
> mVtdUnitInformation[Index].PciDeviceInfo.PciDescriptorNumber; SubIndex++) {
> +      DEBUG ((DEBUG_INFO, "  PCI S%04X B%02x D%02x F%02x - %d\n",
> +        mVtdUnitInformation[Index].Segment,
> +
> mVtdUnitInformation[Index].PciDeviceInfo.PciDescriptors[SubIndex].Bits.Bus,
> +
> mVtdUnitInformation[Index].PciDeviceInfo.PciDescriptors[SubIndex].Bits.Device
> ,
> +
> mVtdUnitInformation[Index].PciDeviceInfo.PciDescriptors[SubIndex].Bits.Functi
> on,
> +        mVtdUnitInformation[Index].PciDeviceInfo.AccessCount[SubIndex]
> +        ));
> +    }
> +  }
> +
>    return EFI_SUCCESS;
>  }
> 
> --
> 2.7.4.windows.1



      reply	other threads:[~2017-08-14  4:14 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-08-11 14:54 [PATCH V2 0/2] Improve IntelVTd performance Jiewen Yao
2017-08-11 14:54 ` [PATCH V2 1/2] IntelSiliconPkg/dsc: Add CacheMaintenanceLib Jiewen Yao
2017-08-11 14:54 ` [PATCH V2 2/2] IntelSiliconPkg/IntelVTdDxe: Improve performance Jiewen Yao
2017-08-14  3:53   ` Zeng, Star
2017-08-14  4:16     ` Yao, Jiewen [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=74D8A39837DF1E4DA445A8C0B3885C503A990951@shsmsx102.ccr.corp.intel.com \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox