Laszlo and Ruiyu,

Could you please take a look at this part? There's a new protocol introduced.

Thanks,
Jian

> -----Original Message-----
> From: edk2-devel [mailto:[email protected]] On Behalf Of Jian J
> Wang
> Sent: Monday, October 23, 2017 8:51 AM
> To: [email protected]
> Cc: Yao, Jiewen <[email protected]>; Dong, Eric <[email protected]>
> Subject: [edk2] [PATCH v3 5/6] UefiCpuPkg/PiSmmCpuDxeSmm: Disable page
> table protection
> 
> > v3
> > According to Jiewen's feedback, implement new protocol
> >     gEdkiiSmmMemoryAttributeProtocolGuid
> > to change memory attributes.
> 
> > v2
> > According to Eric's feedback:
> > a. Enclose bit-or with parentheses
> > b. Add code in 32-bit code to bypass setting page table to read-only
> 
> Heap guard feature will update page attributes frequently. The page table
> should not set to be read-only if heap guard feature is enabled for SMM
> mode. Otherwise this feature cannot work.
> 
> Cc: Eric Dong <[email protected]>
> Cc: Jiewen Yao <[email protected]>
> Suggested-by: Ayellet Wolman <[email protected]>
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Jian J Wang <[email protected]>
> ---
>  UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/PageTbl.c           |   7 +
>  UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.c         |  20 +++
>  UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h         |  98
> +++++++++++++
>  UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf       |   2 +
>  UefiCpuPkg/PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c | 163
> +++++++++++++++++++++
>  UefiCpuPkg/PiSmmCpuDxeSmm/X64/PageTbl.c            |   3 +-
>  6 files changed, 292 insertions(+), 1 deletion(-)
> 
> diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/PageTbl.c
> b/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/PageTbl.c
> index f295c2ebf2..27c11f1b8d 100644
> --- a/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/PageTbl.c
> +++ b/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/PageTbl.c
> @@ -184,6 +184,13 @@ SetPageTableAttributes (
>    BOOLEAN               IsSplitted;
>    BOOLEAN               PageTableSplitted;
> 
> +  //
> +  // Don't mark page table as read-only if heap guard is enabled.
> +  //
> +  if ((PcdGet8 (PcdHeapGuardPropertyMask) & (BIT3 | BIT2)) != 0) {
> +    return ;
> +  }
> +
>    DEBUG ((DEBUG_INFO, "SetPageTableAttributes\n"));
> 
>    //
> diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.c
> b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.c
> index 282d2e6981..8635f2d2c8 100755
> --- a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.c
> +++ b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.c
> @@ -76,6 +76,15 @@ EFI_SMM_CPU_PROTOCOL  mSmmCpu  = {
>    SmmWriteSaveState
>  };
> 
> +///
> +/// SMM Memory Attribute Protocol instance
> +///
> +EFI_SMM_MEMORY_ATTRIBUTE_PROTOCOL  mSmmMemoryAttribute  = {
> +  EdkiiSmmGetMemoryAttributes,
> +  EdkiiSmmSetMemoryAttributes,
> +  EdkiiSmmClearMemoryAttributes
> +};
> +
>  EFI_CPU_INTERRUPT_HANDLER
> mExternalVectorTable[EXCEPTION_VECTOR_NUMBER];
> 
>  //
> @@ -893,6 +902,17 @@ PiCpuSmmEntry (
>                      );
>    ASSERT_EFI_ERROR (Status);
> 
> +  //
> +  // Install the SMM Memory Attribute Protocol into SMM protocol database
> +  //
> +  Status = gSmst->SmmInstallProtocolInterface (
> +                    &mSmmCpuHandle,
> +                    &gEdkiiSmmMemoryAttributeProtocolGuid,
> +                    EFI_NATIVE_INTERFACE,
> +                    &mSmmMemoryAttribute
> +                    );
> +  ASSERT_EFI_ERROR (Status);
> +
>    //
>    // Expose address of CPU Hot Plug Data structure if CPU hot plug is 
> supported.
>    //
> diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h
> b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h
> index 1cf85c1481..e1c231e10b 100644
> --- a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h
> +++ b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h
> @@ -25,6 +25,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY
> KIND, EITHER EXPRESS OR IMPLIED.
>  #include <Protocol/SmmAccess2.h>
>  #include <Protocol/SmmReadyToLock.h>
>  #include <Protocol/SmmCpuService.h>
> +#include <Protocol/SmmMemoryAttribute.h>
> 
>  #include <Guid/AcpiS3Context.h>
>  #include <Guid/PiSmmMemoryAttributesTable.h>
> @@ -1068,4 +1069,101 @@ TransferApToSafeState (
>    IN UINTN  NumberToFinishAddress
>    );
> 
> +/**
> +  This function set given attributes of the memory region specified by
> +  BaseAddress and Length.
> +
> +  @param  This              The EFI_SMM_MEMORY_ATTRIBUTE_PROTOCOL
> instance.
> +  @param  BaseAddress       The physical address that is the start address of
> +                            a memory region.
> +  @param  Length            The size in bytes of the memory region.
> +  @param  Attributes        The bit mask of attributes to set for the memory
> +                            region.
> +
> +  @retval EFI_SUCCESS           The attributes were set for the memory 
> region.
> +  @retval EFI_INVALID_PARAMETER Length is zero.
> +                                Attributes specified an illegal combination 
> of
> +                                attributes that cannot be set together.
> +  @retval EFI_UNSUPPORTED       The processor does not support one or more
> +                                bytes of the memory resource range specified
> +                                by BaseAddress and Length.
> +                                The bit mask of attributes is not support for
> +                                the memory resource range specified by
> +                                BaseAddress and Length.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +EdkiiSmmSetMemoryAttributes (
> +  IN EFI_SMM_MEMORY_ATTRIBUTE_PROTOCOL  *This,
> +  IN  EFI_PHYSICAL_ADDRESS              BaseAddress,
> +  IN  UINT64                            Length,
> +  IN  UINT64                            Attributes
> +  );
> +
> +/**
> +  This function clears given attributes of the memory region specified by
> +  BaseAddress and Length.
> +
> +  @param  This              The EFI_SMM_MEMORY_ATTRIBUTE_PROTOCOL
> instance.
> +  @param  BaseAddress       The physical address that is the start address of
> +                            a memory region.
> +  @param  Length            The size in bytes of the memory region.
> +  @param  Attributes        The bit mask of attributes to set for the memory
> +                            region.
> +
> +  @retval EFI_SUCCESS           The attributes were set for the memory 
> region.
> +  @retval EFI_INVALID_PARAMETER Length is zero.
> +                                Attributes specified an illegal combination 
> of
> +                                attributes that cannot be set together.
> +  @retval EFI_UNSUPPORTED       The processor does not support one or more
> +                                bytes of the memory resource range specified
> +                                by BaseAddress and Length.
> +                                The bit mask of attributes is not support for
> +                                the memory resource range specified by
> +                                BaseAddress and Length.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +EdkiiSmmClearMemoryAttributes (
> +  IN EFI_SMM_MEMORY_ATTRIBUTE_PROTOCOL  *This,
> +  IN  EFI_PHYSICAL_ADDRESS              BaseAddress,
> +  IN  UINT64                            Length,
> +  IN  UINT64                            Attributes
> +  );
> +
> +/**
> +  This function retrieve the attributes of the memory region specified by
> +  BaseAddress and Length. If different attributes are got from different part
> +  of the memory region, EFI_NO_MAPPING will be returned.
> +
> +  @param  This              The EFI_SMM_MEMORY_ATTRIBUTE_PROTOCOL
> instance.
> +  @param  BaseAddress       The physical address that is the start address of
> +                            a memory region.
> +  @param  Length            The size in bytes of the memory region.
> +  @param  Attributes        Pointer to attributes returned.
> +
> +  @retval EFI_SUCCESS           The attributes got for the memory region.
> +  @retval EFI_INVALID_PARAMETER Length is zero.
> +                                Attributes is NULL.
> +  @retval EFI_NO_MAPPING        Attributes are not consistent cross the
> memory
> +                                region.
> +  @retval EFI_UNSUPPORTED       The processor does not support one or more
> +                                bytes of the memory resource range specified
> +                                by BaseAddress and Length.
> +                                The bit mask of attributes is not support for
> +                                the memory resource range specified by
> +                                BaseAddress and Length.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +EdkiiSmmGetMemoryAttributes (
> +  IN EFI_SMM_MEMORY_ATTRIBUTE_PROTOCOL  *This,
> +  IN  EFI_PHYSICAL_ADDRESS              BaseAddress,
> +  IN  UINT64                            Length,
> +  IN  UINT64                            *Attributes
> +  );
> +
>  #endif
> diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf
> b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf
> index 099792e6ce..43d9edd0d5 100644
> --- a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf
> +++ b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf
> @@ -129,6 +129,7 @@
>    gEfiSmmCpuProtocolGuid                   ## PRODUCES
>    gEfiSmmReadyToLockProtocolGuid           ## NOTIFY
>    gEfiSmmCpuServiceProtocolGuid            ## PRODUCES
> +  gEdkiiSmmMemoryAttributeProtocolGuid     ## PRODUCES
> 
>  [Guids]
>    gEfiAcpiVariableGuid                     ## SOMETIMES_CONSUMES ## HOB # it 
> is
> used for S3 boot.
> @@ -159,6 +160,7 @@
>    gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmStaticPageTable               ##
> CONSUMES
>    gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiS3Enable                   ## 
> CONSUMES
>    gEfiMdeModulePkgTokenSpaceGuid.PcdPteMemoryEncryptionAddressOrMask
> ## CONSUMES
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdHeapGuardPropertyMask               ##
> CONSUMES
> 
>  [Depex]
>    gEfiMpServiceProtocolGuid
> diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c
> b/UefiCpuPkg/PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c
> index 3ad5256f1e..eb5e639e4b 100644
> --- a/UefiCpuPkg/PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c
> +++ b/UefiCpuPkg/PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c
> @@ -1120,3 +1120,166 @@ IsSmmCommBufferForbiddenAddress (
>    }
>    return FALSE;
>  }
> +
> +/**
> +  This function set given attributes of the memory region specified by
> +  BaseAddress and Length.
> +
> +  @param  This              The EFI_SMM_MEMORY_ATTRIBUTE_PROTOCOL
> instance.
> +  @param  BaseAddress       The physical address that is the start address of
> +                            a memory region.
> +  @param  Length            The size in bytes of the memory region.
> +  @param  Attributes        The bit mask of attributes to set for the memory
> +                            region.
> +
> +  @retval EFI_SUCCESS           The attributes were set for the memory 
> region.
> +  @retval EFI_INVALID_PARAMETER Length is zero.
> +                                Attributes specified an illegal combination 
> of
> +                                attributes that cannot be set together.
> +  @retval EFI_UNSUPPORTED       The processor does not support one or more
> +                                bytes of the memory resource range specified
> +                                by BaseAddress and Length.
> +                                The bit mask of attributes is not support for
> +                                the memory resource range specified by
> +                                BaseAddress and Length.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +EdkiiSmmSetMemoryAttributes (
> +  IN EFI_SMM_MEMORY_ATTRIBUTE_PROTOCOL  *This,
> +  IN  EFI_PHYSICAL_ADDRESS              BaseAddress,
> +  IN  UINT64                            Length,
> +  IN  UINT64                            Attributes
> +  )
> +{
> +  return SmmSetMemoryAttributes (BaseAddress, Length, Attributes);
> +}
> +
> +/**
> +  This function clears given attributes of the memory region specified by
> +  BaseAddress and Length.
> +
> +  @param  This              The EFI_SMM_MEMORY_ATTRIBUTE_PROTOCOL
> instance.
> +  @param  BaseAddress       The physical address that is the start address of
> +                            a memory region.
> +  @param  Length            The size in bytes of the memory region.
> +  @param  Attributes        The bit mask of attributes to set for the memory
> +                            region.
> +
> +  @retval EFI_SUCCESS           The attributes were set for the memory 
> region.
> +  @retval EFI_INVALID_PARAMETER Length is zero.
> +                                Attributes specified an illegal combination 
> of
> +                                attributes that cannot be set together.
> +  @retval EFI_UNSUPPORTED       The processor does not support one or more
> +                                bytes of the memory resource range specified
> +                                by BaseAddress and Length.
> +                                The bit mask of attributes is not support for
> +                                the memory resource range specified by
> +                                BaseAddress and Length.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +EdkiiSmmClearMemoryAttributes (
> +  IN EFI_SMM_MEMORY_ATTRIBUTE_PROTOCOL  *This,
> +  IN  EFI_PHYSICAL_ADDRESS              BaseAddress,
> +  IN  UINT64                            Length,
> +  IN  UINT64                            Attributes
> +  )
> +{
> +  return SmmClearMemoryAttributes (BaseAddress, Length, Attributes);
> +}
> +
> +/**
> +  This function retrieve the attributes of the memory region specified by
> +  BaseAddress and Length. If different attributes are got from different part
> +  of the memory region, EFI_NO_MAPPING will be returned.
> +
> +  @param  This              The EFI_SMM_MEMORY_ATTRIBUTE_PROTOCOL
> instance.
> +  @param  BaseAddress       The physical address that is the start address of
> +                            a memory region.
> +  @param  Length            The size in bytes of the memory region.
> +  @param  Attributes        Pointer to attributes returned.
> +
> +  @retval EFI_SUCCESS           The attributes got for the memory region.
> +  @retval EFI_INVALID_PARAMETER Length is zero.
> +                                Attributes is NULL.
> +  @retval EFI_NO_MAPPING        Attributes are not consistent cross the
> memory
> +                                region.
> +  @retval EFI_UNSUPPORTED       The processor does not support one or more
> +                                bytes of the memory resource range specified
> +                                by BaseAddress and Length.
> +                                The bit mask of attributes is not support for
> +                                the memory resource range specified by
> +                                BaseAddress and Length.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +EdkiiSmmGetMemoryAttributes (
> +  IN EFI_SMM_MEMORY_ATTRIBUTE_PROTOCOL  *This,
> +  IN  EFI_PHYSICAL_ADDRESS              BaseAddress,
> +  IN  UINT64                            Length,
> +  IN  UINT64                            *Attributes
> +  )
> +{
> +  EFI_PHYSICAL_ADDRESS  Address;
> +  UINT64                *PageEntry;
> +  UINT64                MemAttr;
> +  PAGE_ATTRIBUTE        PageAttr;
> +  INT64                 Size;
> +
> +  if (Length < SIZE_4KB || Attributes == NULL) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  Size = (INT64)Length;
> +  MemAttr = (UINT64)-1;
> +
> +  do {
> +
> +    PageEntry = GetPageTableEntry (BaseAddress, &PageAttr);
> +    if (PageEntry == NULL || PageAttr == PageNone) {
> +      return EFI_UNSUPPORTED;
> +    }
> +
> +    //
> +    // If the memory range is cross page table boundary, make sure they
> +    // share the same attribute. Return EFI_NO_MAPPING if not.
> +    //
> +    *Attributes = GetAttributesFromPageEntry (PageEntry);
> +    if (MemAttr != (UINT64)-1 && *Attributes != MemAttr) {
> +      return EFI_NO_MAPPING;
> +    }
> +
> +    switch (PageAttr) {
> +    case Page4K:
> +      Address     = *PageEntry & ~mAddressEncMask &
> PAGING_4K_ADDRESS_MASK_64;
> +      Size        -= (SIZE_4KB - (BaseAddress - Address));
> +      BaseAddress += (SIZE_4KB - (BaseAddress - Address));
> +      break;
> +
> +    case Page2M:
> +      Address     = *PageEntry & ~mAddressEncMask &
> PAGING_2M_ADDRESS_MASK_64;
> +      Size        -= SIZE_2MB - (BaseAddress - Address);
> +      BaseAddress += SIZE_2MB - (BaseAddress - Address);
> +      break;
> +
> +    case Page1G:
> +      Address     = *PageEntry & ~mAddressEncMask &
> PAGING_1G_ADDRESS_MASK_64;
> +      Size        -= SIZE_1GB - (BaseAddress - Address);
> +      BaseAddress += SIZE_1GB - (BaseAddress - Address);
> +      break;
> +
> +    default:
> +      return EFI_UNSUPPORTED;
> +    }
> +
> +    MemAttr = *Attributes;
> +
> +  } while (Size > 0);
> +
> +  return EFI_SUCCESS;
> +}
> +
> diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/X64/PageTbl.c
> b/UefiCpuPkg/PiSmmCpuDxeSmm/X64/PageTbl.c
> index 3dde80f9ba..4d4668a0c6 100644
> --- a/UefiCpuPkg/PiSmmCpuDxeSmm/X64/PageTbl.c
> +++ b/UefiCpuPkg/PiSmmCpuDxeSmm/X64/PageTbl.c
> @@ -902,7 +902,8 @@ SetPageTableAttributes (
>    BOOLEAN               IsSplitted;
>    BOOLEAN               PageTableSplitted;
> 
> -  if (!mCpuSmmStaticPageTable) {
> +  if (!mCpuSmmStaticPageTable
> +      || (PcdGet8 (PcdHeapGuardPropertyMask) & (BIT3 | BIT2)) != 0) {
>      return ;
>    }
> 
> --
> 2.14.1.windows.1
> 
> _______________________________________________
> edk2-devel mailing list
> [email protected]
> https://lists.01.org/mailman/listinfo/edk2-devel
_______________________________________________
edk2-devel mailing list
[email protected]
https://lists.01.org/mailman/listinfo/edk2-devel

Reply via email to