public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Duran, Leo" <leo.duran@amd.com>
To: "'Zeng, Star'" <star.zeng@intel.com>,
	"Yao, Jiewen" <jiewen.yao@intel.com>,
	"edk2-devel@ml01.01.org" <edk2-devel@ml01.01.org>
Cc: "Tian, Feng" <feng.tian@intel.com>,
	"Singh, Brijesh" <brijesh.singh@amd.com>
Subject: Re: [PATCH] MdeModulePkg/Core/Dxe: Clear SEV mask on MMIO regions
Date: Fri, 24 Mar 2017 14:39:48 +0000	[thread overview]
Message-ID: <DM5PR12MB12436DBFDB0F7AEBFC5F7176F93E0@DM5PR12MB1243.namprd12.prod.outlook.com> (raw)
In-Reply-To: <0C09AFA07DD0434D9E2A0C6AEB0483103B84EB12@shsmsx102.ccr.corp.intel.com>

Jiewen, Star,
Thanks for the prompt & detailed review. I'll certainly consider your feedback.
Leo.

> -----Original Message-----
> From: Zeng, Star [mailto:star.zeng@intel.com]
> Sent: Friday, March 24, 2017 2:57 AM
> To: Yao, Jiewen <jiewen.yao@intel.com>; Duran, Leo
> <leo.duran@amd.com>; edk2-devel@ml01.01.org
> Cc: Tian, Feng <feng.tian@intel.com>; Singh, Brijesh
> <brijesh.singh@amd.com>; Zeng, Star <star.zeng@intel.com>
> Subject: RE: [PATCH] MdeModulePkg/Core/Dxe: Clear SEV mask on MMIO
> regions
> 
> Jiewen,
> 
> I like the solution you proposed. :)
> 
> Thanks,
> Star
> -----Original Message-----
> From: Yao, Jiewen
> Sent: Friday, March 24, 2017 3:49 PM
> To: Zeng, Star <star.zeng@intel.com>; Leo Duran <leo.duran@amd.com>;
> edk2-devel@ml01.01.org
> Cc: Tian, Feng <feng.tian@intel.com>; Brijesh Singh
> <brijesh.singh@amd.com>; Zeng, Star <star.zeng@intel.com>
> Subject: RE: [PATCH] MdeModulePkg/Core/Dxe: Clear SEV mask on MMIO
> regions
> 
> Hi Duran
> I have a little concern about this patch, because we do not introduce any CPU
> specific thing in DxeCore so far.
> 
> I think the basic requirement for SEV is to encrypt system memory, but not
> MMIO. (Please correct me if I am wrong.)
> 
> If that is the case, I would like to propose another solution for your
> consideration.
> 
> 1) In PEI phage, a platform should report PI resource description hob to
> describe system resource, including system memory, and MMIO.
> 
> 2) The DxeIpl can be updated to parse the PI resource description hob to get
> all system memory (DRAM) and MMIO. The DxeIpl can setup page table
> based upon the SEV policy on DRAM/MMIO. I think we should set SEV mask
> for DRAM (no matter it is tested or untested), but always clear SEV mask for
> MMIO and all rest.
> 
> 3) When DxeCore gets control, the page table only has DRAM as encrypted,
> all rest MMIO as decrypted.
> 
> 4) In DXE phase, if a platform module wants to add new DRAM resource, the
> entity which submit ADD request needs to update page table. (NOTE: If a
> platform just want to convert an UNTESTED DRAM to a TESTED DRAM, this
> entity does not update page table, because it is already encrypted in DxeIpl.)
> If a platform module wants to add new MMIO resource, this entity does not
> update table, because it is already decrypted in DxeIpl.)
> 
> Can above flow meet the AMD SEV requirement?
> 
> Thank you
> Yao Jiewen
> 
> 
> 
> > -----Original Message-----
> > From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of
> > Zeng, Star
> > Sent: Friday, March 24, 2017 3:20 PM
> > To: Leo Duran <leo.duran@amd.com>; edk2-devel@ml01.01.org
> > Cc: Tian, Feng <feng.tian@intel.com>; Brijesh Singh
> > <brijesh.singh@amd.com>; Zeng, Star <star.zeng@intel.com>
> > Subject: Re: [edk2] [PATCH] MdeModulePkg/Core/Dxe: Clear SEV mask on
> > MMIO regions
> >
> > I have comments below.
> >
> > 1. Why need to call ConvertEncryptionOnAddressRange() at
> > GCD_FREE_MEMORY_OPERATION case?
> GCD_FREE_MEMORY_OPERATION does not
> > change the Entry->GcdMemoryType.
> > 2. I think it is better to use if (Entry->GcdMemoryType ==
> > EfiGcdMemoryTypeMemoryMappedIo) instead of if (Entry->Capabilities &
> > EFI_MEMORY_PORT_IO) for GCD_REMOVE_MEMORY_OPERATION case.
> > 3. Why need to use PAGING_4K_ADDRESS_MASK_64 in GcdHelper.c? Why
> need
> > to define PAGING_2M_ADDRESS_MASK_64?
> > 4. Why need to unmask Cr3 like below in GcdHelper.c? The PageTables is
> > not masked at DxeIpl before written to CR3. Only the table entry needs
> > to be unmask in GcdHelper.c, right?
> >   GcdHelper.c: Cr3 & ~AddressEncMask
> >   DxeIpl: AsmWriteCr3 (PageTables);
> > 5. Do you need to add dummy GcdHelper.c for other archs? Do you need
> > to put GcdHelperCommon.c and GcdHelper.h under the arch IA32 and X64
> > as other archs do not need them?
> >
> >
> > Thanks,
> > Star
> > -----Original Message-----
> > From: Leo Duran [mailto:leo.duran@amd.com]
> > Sent: Friday, March 24, 2017 10:51 AM
> > To: edk2-devel@ml01.01.org
> > Cc: Leo Duran <leo.duran@amd.com>; Tian, Feng <feng.tian@intel.com>;
> > Zeng, Star <star.zeng@intel.com>; Brijesh Singh
> > <brijesh.singh@amd.com>
> > Subject: [PATCH] MdeModulePkg/Core/Dxe: Clear SEV mask on MMIO
> regions
> >
> > This patch intercepts MMIO configuration in the GCD module to ensure
> > those regions are unmasked.
> >
> > Cc: Feng Tian <feng.tian@intel.com>
> > Cc: Star Zeng <star.zeng@intel.com>
> > Cc: Brijesh Singh <brijesh.singh@amd.com>
> > Contributed-under: TianoCore Contribution Agreement 1.0
> > Signed-off-by: Leo Duran <leo.duran@amd.com>
> > ---
> >  MdeModulePkg/Core/Dxe/DxeMain.inf           |  11 ++
> >  MdeModulePkg/Core/Dxe/Gcd/Gcd.c             |  28 ++++++
> >  MdeModulePkg/Core/Dxe/Gcd/GcdHelper.h       | 151
> > ++++++++++++++++++++++++++++
> >  MdeModulePkg/Core/Dxe/Gcd/GcdHelperCommon.c | 120
> > ++++++++++++++++++++++
> MdeModulePkg/Core/Dxe/Gcd/Ia32/GcdHelper.c
> > | 115 +++++++++++++++++++++
> >  MdeModulePkg/Core/Dxe/Gcd/X64/GcdHelper.c   | 129
> > ++++++++++++++++++++++++
> >  6 files changed, 554 insertions(+)
> >  create mode 100644 MdeModulePkg/Core/Dxe/Gcd/GcdHelper.h
> >  create mode 100644
> MdeModulePkg/Core/Dxe/Gcd/GcdHelperCommon.c
> >  create mode 100644 MdeModulePkg/Core/Dxe/Gcd/Ia32/GcdHelper.c
> >  create mode 100644 MdeModulePkg/Core/Dxe/Gcd/X64/GcdHelper.c
> >
> > diff --git a/MdeModulePkg/Core/Dxe/DxeMain.inf
> > b/MdeModulePkg/Core/Dxe/DxeMain.inf
> > index 30d5984..183d1e7 100644
> > --- a/MdeModulePkg/Core/Dxe/DxeMain.inf
> > +++ b/MdeModulePkg/Core/Dxe/DxeMain.inf
> > @@ -4,6 +4,8 @@
> >  #  It provides an implementation of DXE Core that is compliant with DXE
> CIS.
> >  #
> >  #  Copyright (c) 2006 - 2017, Intel Corporation. All rights
> > reserved.<BR>
> > +#  Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR> #
> >  #  This program and the accompanying materials  #  are licensed and
> > made available under the terms and conditions of the BSD License  #
> > which accompanies this distribution.  The full text of the license may
> > be found at @@
> > -51,6 +53,8 @@
> >    Hand/Handle.h
> >    Gcd/Gcd.c
> >    Gcd/Gcd.h
> > +  Gcd/GcdHelperCommon.c
> > +  Gcd/GcdHelper.h
> >    Mem/Pool.c
> >    Mem/Page.c
> >    Mem/MemData.c
> > @@ -73,6 +77,12 @@
> >    DxeMain/DxeProtocolNotify.c
> >    DxeMain/DxeMain.c
> >
> > +[Sources.Ia32]
> > +  Gcd/Ia32/GcdHelper.c
> > +
> > +[Sources.X64]
> > +  Gcd/X64/GcdHelper.c
> > +
> >  [Packages]
> >    MdePkg/MdePkg.dec
> >    MdeModulePkg/MdeModulePkg.dec
> > @@ -192,6 +202,7 @@
> >    gEfiMdeModulePkgTokenSpaceGuid.PcdPropertiesTableEnable
> > ## CONSUMES
> >    gEfiMdeModulePkgTokenSpaceGuid.PcdImageProtectionPolicy
> > ## CONSUMES
> >    gEfiMdeModulePkgTokenSpaceGuid.PcdDxeNxMemoryProtectionPolicy
> > ## CONSUMES
> > +
> >
> gEfiMdeModulePkgTokenSpaceGuid.PcdPteMemoryEncryptionAddressOrM
> ask
> > ## CONSUMES
> >
> >  # [Hob]
> >  # RESOURCE_DESCRIPTOR   ## CONSUMES
> > diff --git a/MdeModulePkg/Core/Dxe/Gcd/Gcd.c
> > b/MdeModulePkg/Core/Dxe/Gcd/Gcd.c index a06f8bb..6f85c21 100644
> > --- a/MdeModulePkg/Core/Dxe/Gcd/Gcd.c
> > +++ b/MdeModulePkg/Core/Dxe/Gcd/Gcd.c
> > @@ -4,6 +4,8 @@
> >    are accessible to the CPU that is executing the DXE core.
> >
> >  Copyright (c) 2006 - 2017, Intel Corporation. All rights
> > reserved.<BR>
> > +Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
> > +
> >  This program and the accompanying materials  are licensed and made
> > available under the terms and conditions of the BSD License  which
> > accompanies this distribution.  The full text of the license may be
> > found at @@ -16,6 +18,7 @@ WITHOUT WARRANTIES OR
> REPRESENTATIONS OF
> > ANY KIND, EITHER EXPRESS OR IMPLIED.
> >
> >  #include "DxeMain.h"
> >  #include "Gcd.h"
> > +#include "GcdHelper.h"
> >
> >  #define MINIMUM_INITIAL_MEMORY_SIZE 0x10000
> >
> > @@ -723,6 +726,7 @@ CoreConvertSpace (
> >    LIST_ENTRY         *StartLink;
> >    LIST_ENTRY         *EndLink;
> >    UINT64             CpuArchAttributes;
> > +  UINT64             AddressEncMask;
> >
> >    if (Length == 0) {
> >      DEBUG ((DEBUG_GCD, "  Status = %r\n", EFI_INVALID_PARAMETER));
> @@
> > -741,6 +745,11 @@ CoreConvertSpace (
> >    }
> >
> >    //
> > +  // Make sure AddressEncMask is contained to smallest supported
> > + address
> > field.
> > +  //
> > +  AddressEncMask = PcdGet64
> (PcdPteMemoryEncryptionAddressOrMask) &
> > + PAGING_1G_ADDRESS_MASK_64;
> > +
> > +  //
> >    // Search for the list of descriptors that cover the range
> > BaseAddress to
> > BaseAddress+Length
> >    //
> >    Status = CoreSearchGcdMapEntry (BaseAddress, Length, &StartLink,
> > &EndLink, Map); @@ -893,6 +902,11 @@ CoreConvertSpace (
> >        Entry->GcdMemoryType = GcdMemoryType;
> >        if (GcdMemoryType == EfiGcdMemoryTypeMemoryMappedIo) {
> >          Entry->Capabilities  = Capabilities | EFI_MEMORY_RUNTIME |
> > EFI_MEMORY_PORT_IO;
> > +        Status = ConvertEncryptionOnAddressRange (BaseAddress,
> > + Length,
> > CLEAR_ADDR_ENC_OPERATION, AddressEncMask);
> > +        if (EFI_ERROR (Status)) {
> > +          DEBUG ((EFI_D_ERROR, "Could not CLEAR EncMask on Range:
> > BaseAddress = 0xlX, Length = 0xlX, Status = %r\n",
> > +            BaseAddress, Length, Status));
> > +        }
> >        } else {
> >          Entry->Capabilities  = Capabilities | EFI_MEMORY_RUNTIME;
> >        }
> > @@ -904,6 +918,13 @@ CoreConvertSpace (
> >      // Free operations
> >      //
> >      case GCD_FREE_MEMORY_OPERATION:
> > +      if (Entry->Capabilities & EFI_MEMORY_PORT_IO) {
> > +        Status = ConvertEncryptionOnAddressRange (BaseAddress,
> > + Length,
> > SET_ADDR_ENC_OPERATION, AddressEncMask);
> > +        if (EFI_ERROR (Status)) {
> > +          DEBUG ((EFI_D_ERROR, "Could not SET EncMask on Range:
> > BaseAddress = 0xlX, Length = 0xlX, Status = %r\n",
> > +            BaseAddress, Length, Status));
> > +        }
> > +      }
> >      case GCD_FREE_IO_OPERATION:
> >        Entry->ImageHandle  = NULL;
> >        Entry->DeviceHandle = NULL;
> > @@ -912,6 +933,13 @@ CoreConvertSpace (
> >      // Remove operations
> >      //
> >      case GCD_REMOVE_MEMORY_OPERATION:
> > +      if (Entry->Capabilities & EFI_MEMORY_PORT_IO) {
> > +        Status = ConvertEncryptionOnAddressRange (BaseAddress,
> > + Length,
> > SET_ADDR_ENC_OPERATION, AddressEncMask);
> > +        if (EFI_ERROR (Status)) {
> > +          DEBUG ((EFI_D_ERROR, "Could not SET EncMask on Range:
> > BaseAddress = 0xlX, Length = 0xlX, Status = %r\n",
> > +            BaseAddress, Length, Status));
> > +        }
> > +      }
> >        Entry->GcdMemoryType = EfiGcdMemoryTypeNonExistent;
> >        Entry->Capabilities  = 0;
> >        break;
> > diff --git a/MdeModulePkg/Core/Dxe/Gcd/GcdHelper.h
> > b/MdeModulePkg/Core/Dxe/Gcd/GcdHelper.h
> > new file mode 100644
> > index 0000000..d6ec339
> > --- /dev/null
> > +++ b/MdeModulePkg/Core/Dxe/Gcd/GcdHelper.h
> > @@ -0,0 +1,151 @@
> > +/** @file
> > +  Definitions for helper functions used by GCD.
> > +
> > +Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
> > +
> > +This program and the accompanying materials are licensed and made
> > +available under the terms and conditions of the BSD License which
> > +accompanies this distribution.  The full text of the license may be
> > +found at http://opensource.org/licenses/bsd-license.php
> > +
> > +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> > +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> EXPRESS
> > OR IMPLIED.
> > +
> > +**/
> > +
> > +#ifndef _GCD_HELPER_H_
> > +#define _GCD_HELPER_H_
> > +
> > +
> > +#pragma pack(1)
> > +//
> > +// Page Table Entry 4KB
> > +//
> > +typedef union {
> > +  struct {
> > +    UINT64  Present:1;                // 0 = Not present in memory, 1 =
> > Present in memory
> > +    UINT64  ReadWrite:1;              // 0 = Read-Only, 1= Read/Write
> > +    UINT64  UserSupervisor:1;         // 0 = Supervisor, 1=User
> > +    UINT64  WriteThrough:1;           // 0 = Write-Back caching,
> > 1=Write-Through caching
> > +    UINT64  CacheDisabled:1;          // 0 = Cached, 1=Non-Cached
> > +    UINT64  Accessed:1;               // 0 = Not accessed, 1 = Accessed
> > (set by CPU)
> > +    UINT64  Dirty:1;                  // 0 = Not Dirty, 1 = written by
> > processor on access to page
> > +    UINT64  PAT:1;                    //
> > +    UINT64  Global:1;                 // 0 = Not global page, 1 = global
> > page TLB not cleared on CR3 write
> > +    UINT64  Available:3;              // Available for use by system
> > software
> > +    UINT64  PageTableBaseAddress:40;  // Page Table Base Address
> > +    UINT64  AvailableHigh:11;         // Available for use by system
> > software
> > +    UINT64  Nx:1;                     // 0 = Execute Code, 1 = No Code
> > Execution
> > +  } Bits;
> > +  UINT64    Uint64;
> > +} PAGE_TABLE_4K_ENTRY;
> > +
> > +//
> > +// Page Table Entry 2MB
> > +//
> > +typedef union {
> > +  struct {
> > +    UINT64  Present:1;                // 0 = Not present in memory, 1 =
> > Present in memory
> > +    UINT64  ReadWrite:1;              // 0 = Read-Only, 1= Read/Write
> > +    UINT64  UserSupervisor:1;         // 0 = Supervisor, 1=User
> > +    UINT64  WriteThrough:1;           // 0 = Write-Back caching,
> > 1=Write-Through caching
> > +    UINT64  CacheDisabled:1;          // 0 = Cached, 1=Non-Cached
> > +    UINT64  Accessed:1;               // 0 = Not accessed, 1 = Accessed
> > (set by CPU)
> > +    UINT64  Dirty:1;                  // 0 = Not Dirty, 1 = written by
> > processor on access to page
> > +    UINT64  MustBe1:1;                // Must be 1
> > +    UINT64  Global:1;                 // 0 = Not global page, 1 = global
> > page TLB not cleared on CR3 write
> > +    UINT64  Available:3;              // Available for use by system
> > software
> > +    UINT64  PAT:1;                    //
> > +    UINT64  MustBeZero:8;             // Must be zero;
> > +    UINT64  PageTableBaseAddress:31;  // Page Table Base Address
> > +    UINT64  AvailableHigh:11;         // Available for use by system
> > software
> > +    UINT64  Nx:1;                     // 0 = Execute Code, 1 = No Code
> > Execution
> > +  } Bits;
> > +  UINT64    Uint64;
> > +} PAGE_TABLE_2M_ENTRY;
> > +#pragma pack()
> > +
> > +
> > +typedef enum {
> > +  CLEAR_ADDR_ENC_OPERATION,
> > +  SET_ADDR_ENC_OPERATION,
> > +  INVALID_ENC_OPERATION
> > +} ADDR_ENC_OPERATION;
> > +
> > +
> > +#define IA32_PG_P                  BIT0
> > +#define IA32_PG_RW                 BIT1
> > +#define IA32_PG_PS                 BIT7
> > +
> > +#define PAGING_4K_ADDRESS_MASK_64  0x000FFFFFFFFFF000ull
> #define
> > +PAGING_2M_ADDRESS_MASK_64  0x000FFFFFFFE00000ull #define
> > +PAGING_1G_ADDRESS_MASK_64  0x000FFFFFC0000000ull
> > +
> > +
> > +/**
> > +  Convert Encryption on address range
> > +
> > +  @param  BaseAddress            Start address of the range
> > +  @param  Length                 Length of the segment
> > +  @param  Operation              Convertion operation (set or clear)
> > +  @param  AddressEncMask         Address Encryption Mask
> > +
> > +  @retval EFI_INVALID_PARAMETER  Length or Address not aligned on
> > EFI_PAGE_SIZE boundary.
> > +  @retval EFI_NO_MAPPING         Missing page table mappings for the
> > specified segment.
> > +  @retval EFI_SUCCESS            Action successfully done.
> > +**/
> > +EFI_STATUS
> > +ConvertEncryptionOnAddressRange (
> > +  IN EFI_PHYSICAL_ADDRESS  BaseAddress,
> > +  IN UINT64                Length,
> > +  IN ADDR_ENC_OPERATION    Operation,
> > +  IN UINT64                AddressEncMask
> > +  );
> > +
> > +/**
> > +  Convert Encryption on page table entry.
> > +
> > +  @param  PageTableEntry         Start address of the range
> > +  @param  Operation              Convertion operation (set or clear)
> > +  @param  AddressEncMask         Address Encryption Mask
> > +
> > +**/
> > +VOID
> > +ConvertEncryptionOnPageTableEntry (
> > +  IN UINT64              *PageTableEntry,
> > +  IN ADDR_ENC_OPERATION  Operation,
> > +  IN UINT64              AddressEncMask
> > +  );
> > +
> > +/**
> > +  Split 1G page to 2M on Encrypted address range.
> > +
> > +  @param[in]      PhysicalAddress       Address of the encryted range.
> > +  @param[in]      AddressEncMask        Address Encryption Mask.
> > +  @param[in, out] PageEntry1G           Pointer to 1G page entry.
> > +
> > +**/
> > +VOID
> > +Split1GPageTo2MPageOnEncRange (
> > +  IN EFI_PHYSICAL_ADDRESS               PhysicalAddress,
> > +  IN UINT64                             AddressEncMask,
> > +  IN OUT UINT64                         *PageEntry1G
> > +  );
> > +
> > +/**
> > +  Split 2M page to 4K on Encrypted address range.
> > +
> > +  @param[in]      PhysicalAddress       Address of the range.
> > +  @param[in]      AddressEncmask        Encryption Mask.
> > +  @param[in, out] PageEntry2M           Pointer to 2M page entry.
> > +
> > +**/
> > +VOID
> > +Split2MPageTo4KPageOnEncRange (
> > +  IN EFI_PHYSICAL_ADDRESS               PhysicalAddress,
> > +  IN UINT64                             AddressEncMask,
> > +  IN OUT UINT64                         *PageEntry2M
> > +  );
> > +
> > +#endif // _GCD_HELPER_H_
> > +
> > diff --git a/MdeModulePkg/Core/Dxe/Gcd/GcdHelperCommon.c
> > b/MdeModulePkg/Core/Dxe/Gcd/GcdHelperCommon.c
> > new file mode 100644
> > index 0000000..1660732
> > --- /dev/null
> > +++ b/MdeModulePkg/Core/Dxe/Gcd/GcdHelperCommon.c
> > @@ -0,0 +1,120 @@
> > +/** @file
> > +  The file contains helper functions used by GCD.
> > +
> > +Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
> > +
> > +This program and the accompanying materials are licensed and made
> > +available under the terms and conditions of the BSD License which
> > +accompanies this distribution.  The full text of the license may be
> > +found at http://opensource.org/licenses/bsd-license.php
> > +
> > +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> > +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> EXPRESS
> > OR IMPLIED.
> > +
> > +**/
> > +
> > +#include "DxeMain.h"
> > +#include "GcdHelper.h"
> > +
> > +
> > +/**
> > +  Split 2M page to 4K on Encrypted address range.
> > +
> > +  @param[in]      PhysicalAddress       Address of the range.
> > +  @param[in]      AddressEncmask        Encryption Mask.
> > +  @param[in, out] PageEntry2M           Pointer to 2M page entry.
> > +
> > +**/
> > +VOID
> > +Split2MPageTo4KPageOnEncRange (
> > +  IN EFI_PHYSICAL_ADDRESS               PhysicalAddress,
> > +  IN UINT64                             AddressEncMask,
> > +  IN OUT UINT64                         *PageEntry2M
> > +  )
> > +{
> > +  EFI_PHYSICAL_ADDRESS                  PhysicalAddress4K;
> > +  UINTN                                 IndexOfPageTableEntries;
> > +  PAGE_TABLE_4K_ENTRY                   *PageTableEntry;
> > +
> > +  PageTableEntry = (PAGE_TABLE_4K_ENTRY *)AllocatePages (1);  ASSERT
> > + (PageTableEntry != NULL);
> > +
> > +  //
> > +  // Fill in 2M page entry.
> > +  //
> > +  *PageEntry2M = (UINT64)(UINTN) PageTableEntry | AddressEncMask |
> > + IA32_PG_P | IA32_PG_RW;
> > +
> > +  PhysicalAddress4K = PhysicalAddress;  for (IndexOfPageTableEntries
> > + = 0; IndexOfPageTableEntries < 512;
> > IndexOfPageTableEntries++, PageTableEntry++, PhysicalAddress4K +=
> > IndexOfPageTableEntries++SIZE_4KB)
> > {
> > +    //
> > +    // Fill in the Page Table entries
> > +    //
> > +    PageTableEntry->Uint64 = (UINT64) PhysicalAddress4K |
> AddressEncMask;
> > +    PageTableEntry->Bits.ReadWrite = 1;
> > +    PageTableEntry->Bits.Present = 1;
> > +  }
> > +}
> > +
> > +
> > +/**
> > +  Split 1G page to 2M on Encrypted address range.
> > +
> > +  @param[in]      PhysicalAddress       Address of the encryted range.
> > +  @param[in]      AddressEncMask        Address Encryption Mask.
> > +  @param[in, out] PageEntry1G           Pointer to 1G page entry.
> > +
> > +**/
> > +VOID
> > +Split1GPageTo2MPageOnEncRange (
> > +  IN EFI_PHYSICAL_ADDRESS               PhysicalAddress,
> > +  IN UINT64                             AddressEncMask,
> > +  IN OUT UINT64                         *PageEntry1G
> > +  )
> > +{
> > +  EFI_PHYSICAL_ADDRESS                  PhysicalAddress2M;
> > +  UINTN                                 IndexOfPageDirectoryEntries;
> > +  PAGE_TABLE_2M_ENTRY                   *PageDirectoryEntry;
> > +
> > +  PageDirectoryEntry = (PAGE_TABLE_2M_ENTRY *)AllocatePages (1);
> > + ASSERT (PageDirectoryEntry != NULL);
> > +
> > +  //
> > +  // Fill in 1G page entry.
> > +  //
> > +  *PageEntry1G = (UINT64)(UINTN) PageDirectoryEntry | AddressEncMask
> > + | IA32_PG_P | IA32_PG_RW;
> > +
> > +  PhysicalAddress2M = PhysicalAddress;  for
> > + (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512;
> > IndexOfPageDirectoryEntries++, PageDirectoryEntry++,
> PhysicalAddress2M
> > IndexOfPageDirectoryEntries+++=
> > SIZE_2MB) {
> > +    //
> > +    // Fill in the Page Directory entries
> > +    //
> > +    PageDirectoryEntry->Uint64 = (UINT64) PhysicalAddress2M |
> > AddressEncMask;
> > +    PageDirectoryEntry->Bits.ReadWrite = 1;
> > +    PageDirectoryEntry->Bits.Present = 1;
> > +    PageDirectoryEntry->Bits.MustBe1 = 1;
> > +  }
> > +}
> > +
> > +
> > +/**
> > +  Convert Encryption on page table entry.
> > +
> > +  @param  PageTableEntry         Start address of the range
> > +  @param  Operation              Convertion operation (set or clear)
> > +  @param  AddressEncMask         Address Encryption Mask
> > +
> > +**/
> > +VOID
> > +ConvertEncryptionOnPageTableEntry (
> > +  IN UINT64              *PageTableEntry,
> > +  IN ADDR_ENC_OPERATION  Operation,
> > +  IN UINT64              AddressEncMask
> > +  )
> > +{
> > +  if (Operation == CLEAR_ADDR_ENC_OPERATION) {
> > +    *PageTableEntry &= ~AddressEncMask;
> > +  } else if (Operation == SET_ADDR_ENC_OPERATION) {
> > +    *PageTableEntry |= AddressEncMask;
> > +  }
> > +}
> > +
> > diff --git a/MdeModulePkg/Core/Dxe/Gcd/Ia32/GcdHelper.c
> > b/MdeModulePkg/Core/Dxe/Gcd/Ia32/GcdHelper.c
> > new file mode 100644
> > index 0000000..4781900
> > --- /dev/null
> > +++ b/MdeModulePkg/Core/Dxe/Gcd/Ia32/GcdHelper.c
> > @@ -0,0 +1,115 @@
> > +/** @file
> > +  The file contains helper functions used by GCD.
> > +
> > +Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
> > +
> > +This program and the accompanying materials are licensed and made
> > +available under the terms and conditions of the BSD License which
> > +accompanies this distribution.  The full text of the license may be
> > +found at http://opensource.org/licenses/bsd-license.php
> > +
> > +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> > +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> EXPRESS
> > OR IMPLIED.
> > +
> > +**/
> > +
> > +#include "DxeMain.h"
> > +#include "GcdHelper.h"
> > +
> > +
> > +/**
> > +  Convert Encryption on address range.
> > +
> > +  @param  BaseAddress            Start address of the range
> > +  @param  Length                 Length of the range
> > +  @param  Operation              Convertion operation (set or clear)
> > +  @param  AddressEncMask         Address Encryption Mask
> > +
> > +  @retval EFI_INVALID_PARAMETER  Length or Address not aligned on
> > EFI_PAGE_SIZE boundary.
> > +  @retval EFI_NO_MAPPING         Missing page table mappings for the
> > specified range.
> > +  @retval EFI_SUCCESS            Action successfully done.
> > +**/
> > +EFI_STATUS
> > +ConvertEncryptionOnAddressRange (
> > +  IN EFI_PHYSICAL_ADDRESS  BaseAddress,
> > +  IN UINT64                Length,
> > +  IN ADDR_ENC_OPERATION    Operation,
> > +  IN UINT64                AddressEncMask
> > +  )
> > +{
> > +  EFI_PHYSICAL_ADDRESS  PhysicalAddress;
> > +  UINT64                *PageTable;
> > +  UINTN                 PTIndex;
> > +  UINT64                Cr3;
> > +
> > +  // Do we have actual work to do?
> > +  if (Length == 0 || AddressEncMask == 0) {
> > +    return EFI_SUCCESS;
> > +  }
> > +
> > +  // PAE *must* be enabled on 32-bit page tables  // (else we can't
> > + configure AddressEncMask)  if ((AsmReadCr4 () & BIT5) == 0) {
> > +    return EFI_SUCCESS;
> > +  }
> > +
> > +  // Make sure we're PAGE_SIZE aligned  if ((BaseAddress &
> > + EFI_PAGE_MASK) || (Length & EFI_PAGE_MASK)) {
> > +    return EFI_INVALID_PARAMETER;
> > +  }
> > +
> > +  // Validate Operation
> > +  if (Operation >= INVALID_ENC_OPERATION) {
> > +    return EFI_INVALID_PARAMETER;
> > +  }
> > +
> > +  Cr3 = AsmReadCr3 ();
> > +  PhysicalAddress = BaseAddress;
> > +
> > +  do {
> > +    // PDPE Present?
> > +    PageTable = (UINT64 *)(UINTN) (Cr3 & ~AddressEncMask &
> > PAGING_4K_ADDRESS_MASK_64);
> > +    PTIndex = BitFieldRead64(PhysicalAddress, 30, 31);
> > +    if ((PageTable[PTIndex] & IA32_PG_P) == 0) {
> > +      return EFI_NO_MAPPING;
> > +    }
> > +
> > +    // PDE Present?
> > +    PageTable = (UINT64 *)(UINTN) (PageTable[PTIndex] &
> > + ~AddressEncMask
> > & PAGING_4K_ADDRESS_MASK_64);
> > +    PTIndex = BitFieldRead64(PhysicalAddress, 21, 29);
> > +    if ((PageTable[PTIndex] & IA32_PG_P) == 0) {
> > +      return EFI_NO_MAPPING;
> > +    }
> > +
> > +    // Is it a 2MB page entry?
> > +    if ((PageTable[PTIndex] & IA32_PG_PS ) != 0) {
> > +      if ((PhysicalAddress & (SIZE_2MB - 1)) == 0 && Length >= SIZE_2MB) {
> > +        // Consume 2MB from the range
> > +        ConvertEncryptionOnPageTableEntry (&PageTable[PTIndex],
> > Operation, AddressEncMask);
> > +        PhysicalAddress += SIZE_2MB;
> > +        Length -= SIZE_2MB;
> > +      } else {
> > +        // Split 2MB page entry to consume 4K chunks
> > +        Split2MPageTo4KPageOnEncRange (PhysicalAddress,
> > + AddressEncMask,
> > &PageTable[PTIndex]);
> > +      }
> > +    } else {
> > +      // PTE Present?
> > +      PageTable = (UINT64 *)(UINTN) (PageTable[PTIndex] &
> > ~AddressEncMask & PAGING_4K_ADDRESS_MASK_64);
> > +      PTIndex = BitFieldRead64(PhysicalAddress, 12, 20);
> > +      if ((PageTable[PTIndex] & IA32_PG_P) == 0) {
> > +        return EFI_NO_MAPPING;
> > +      }
> > +
> > +      // Consume 4KB from the range
> > +      ConvertEncryptionOnPageTableEntry (&PageTable[PTIndex],
> > + Operation,
> > AddressEncMask);
> > +      PhysicalAddress += SIZE_4KB;
> > +      Length -= SIZE_4KB;
> > +    }
> > +  } while (Length);
> > +
> > +  // Flush TLB
> > +  AsmWriteCr3 (Cr3);
> > +
> > +  return EFI_SUCCESS;
> > +}
> > +
> > diff --git a/MdeModulePkg/Core/Dxe/Gcd/X64/GcdHelper.c
> > b/MdeModulePkg/Core/Dxe/Gcd/X64/GcdHelper.c
> > new file mode 100644
> > index 0000000..5943f7a
> > --- /dev/null
> > +++ b/MdeModulePkg/Core/Dxe/Gcd/X64/GcdHelper.c
> > @@ -0,0 +1,129 @@
> > +/** @file
> > +  The file contains helper functions used by GCD.
> > +
> > +Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
> > +
> > +This program and the accompanying materials are licensed and made
> > +available under the terms and conditions of the BSD License which
> > +accompanies this distribution.  The full text of the license may be
> > +found at http://opensource.org/licenses/bsd-license.php
> > +
> > +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> > +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> EXPRESS
> > OR IMPLIED.
> > +
> > +**/
> > +
> > +#include "DxeMain.h"
> > +#include "GcdHelper.h"
> > +
> > +
> > +/**
> > +  Convert Encryption on address range.
> > +
> > +  @param  BaseAddress            Start address of the range
> > +  @param  Length                 Length of the range
> > +  @param  Operation              Convertion operation (set or clear)
> > +  @param  AddressEncMask         Address Encryption Mask
> > +
> > +  @retval EFI_INVALID_PARAMETER  Length or Address not aligned on
> > EFI_PAGE_SIZE boundary.
> > +  @retval EFI_NO_MAPPING         Missing page table mappings for the
> > specified range.
> > +  @retval EFI_SUCCESS            Action successfully done.
> > +**/
> > +EFI_STATUS
> > +ConvertEncryptionOnAddressRange (
> > +  IN EFI_PHYSICAL_ADDRESS  BaseAddress,
> > +  IN UINT64                Length,
> > +  IN ADDR_ENC_OPERATION    Operation,
> > +  IN UINT64                AddressEncMask
> > +  )
> > +{
> > +  EFI_PHYSICAL_ADDRESS  PhysicalAddress;
> > +  UINT64                *PageTable;
> > +  UINTN                 PTIndex;
> > +  UINT64                Cr3;
> > +
> > +  // Do we have actual work to do?
> > +  if (Length == 0 || AddressEncMask == 0) {
> > +    return EFI_SUCCESS;
> > +  }
> > +
> > +  // Make sure we're PAGE_SIZE aligned  if ((BaseAddress &
> > + EFI_PAGE_MASK) || (Length & EFI_PAGE_MASK)) {
> > +    return EFI_INVALID_PARAMETER;
> > +  }
> > +
> > +  // Validate Operation
> > +  if (Operation >= INVALID_ENC_OPERATION) {
> > +    return EFI_INVALID_PARAMETER;
> > +  }
> > +
> > +  Cr3 = AsmReadCr3 ();
> > +  PhysicalAddress = BaseAddress;
> > +
> > +  do {
> > +    // PML4E Present?
> > +    PageTable = (UINT64 *)(UINTN) (Cr3 & ~AddressEncMask &
> > PAGING_4K_ADDRESS_MASK_64);
> > +    PTIndex = BitFieldRead64(PhysicalAddress, 39, 47);
> > +    if ((PageTable[PTIndex] & IA32_PG_P) == 0) {
> > +      return EFI_NO_MAPPING;
> > +    }
> > +
> > +    // PDPE Present?
> > +    PageTable = (UINT64 *)(UINTN) (PageTable[PTIndex] &
> > + ~AddressEncMask
> > & PAGING_4K_ADDRESS_MASK_64);
> > +    PTIndex = BitFieldRead64(PhysicalAddress, 30, 38);
> > +    if ((PageTable[PTIndex] & IA32_PG_P) == 0) {
> > +      return EFI_NO_MAPPING;
> > +    }
> > +
> > +    // Is it a 1GB page entry?
> > +    if ((PageTable[PTIndex] & IA32_PG_PS ) != 0) {
> > +      if ((PhysicalAddress & (SIZE_1GB - 1)) == 0 && Length >= SIZE_1GB) {
> > +        // Consume 1GB from the range
> > +        ConvertEncryptionOnPageTableEntry (&PageTable[PTIndex],
> > Operation, AddressEncMask);
> > +        PhysicalAddress += SIZE_1GB;
> > +        Length -= SIZE_1GB;
> > +      } else {
> > +        // Split 1G page entry to attempt consuming 2MB chunks
> > +        Split1GPageTo2MPageOnEncRange (PhysicalAddress,
> > + AddressEncMask,
> > &PageTable[PTIndex]);
> > +      }
> > +    } else {
> > +      // PDE Present?
> > +      PageTable = (UINT64 *)(UINTN) (PageTable[PTIndex] &
> > ~AddressEncMask & PAGING_4K_ADDRESS_MASK_64);
> > +      PTIndex = BitFieldRead64(PhysicalAddress, 21, 29);
> > +      if ((PageTable[PTIndex] & IA32_PG_P) == 0) {
> > +        return EFI_NO_MAPPING;
> > +      }
> > +
> > +      // Is it a 2MB page entry?
> > +      if ((PageTable[PTIndex] & IA32_PG_PS ) != 0) {
> > +        if ((PhysicalAddress & (SIZE_2MB - 1)) == 0 && Length >= SIZE_2MB) {
> > +          // Consume 2MB from the range
> > +          ConvertEncryptionOnPageTableEntry (&PageTable[PTIndex],
> > Operation, AddressEncMask);
> > +          PhysicalAddress += SIZE_2MB;
> > +          Length -= SIZE_2MB;
> > +        } else {
> > +          // Split 2MB page entry to consume 4K chunks
> > +          Split2MPageTo4KPageOnEncRange (PhysicalAddress,
> > AddressEncMask, &PageTable[PTIndex]);
> > +        }
> > +      } else {
> > +        // PTE Present?
> > +        PageTable = (UINT64 *)(UINTN) (PageTable[PTIndex] &
> > ~AddressEncMask & PAGING_4K_ADDRESS_MASK_64);
> > +        PTIndex = BitFieldRead64(PhysicalAddress, 12, 20);
> > +        if ((PageTable[PTIndex] & IA32_PG_P) == 0) {
> > +          return EFI_NO_MAPPING;
> > +        }
> > +
> > +        // Consume 4KB from the range
> > +        ConvertEncryptionOnPageTableEntry (&PageTable[PTIndex],
> > Operation, AddressEncMask);
> > +        PhysicalAddress += SIZE_4KB;
> > +        Length -= SIZE_4KB;
> > +      }
> > +    }
> > +  } while (Length);
> > +
> > +  // Flush TLB
> > +  AsmWriteCr3 (Cr3);
> > +
> > +  return EFI_SUCCESS;
> > +}
> > +
> > --
> > 2.7.4
> >
> > _______________________________________________
> > edk2-devel mailing list
> > edk2-devel@lists.01.org
> > https://lists.01.org/mailman/listinfo/edk2-devel


      reply	other threads:[~2017-03-24 14:39 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-03-24  2:51 [PATCH] MdeModulePkg/Core/Dxe: Clear SEV mask on MMIO regions Leo Duran
2017-03-24  2:51 ` Leo Duran
2017-03-24  7:20   ` Zeng, Star
2017-03-24  7:48     ` Yao, Jiewen
2017-03-24  7:57       ` Zeng, Star
2017-03-24 14:39         ` Duran, Leo [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=DM5PR12MB12436DBFDB0F7AEBFC5F7176F93E0@DM5PR12MB1243.namprd12.prod.outlook.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