public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Brijesh Singh" <brijesh.singh@amd.com>
To: devel@edk2.groups.io
Cc: brijesh.singh@amd.com, James Bottomley <jejb@linux.ibm.com>,
	Min Xu <min.m.xu@intel.com>, Jiewen Yao <jiewen.yao@intel.com>,
	Tom Lendacky <thomas.lendacky@amd.com>,
	Jordan Justen <jordan.l.justen@intel.com>,
	Ard Biesheuvel <ardb+tianocore@kernel.org>,
	Erdem Aktas <erdemaktas@google.com>,
	Michael Roth <Michael.Roth@amd.com>,
	Gerd Hoffmann <kraxel@redhat.com>,
	Eric Dong <eric.dong@intel.com>, Ray Ni <ray.ni@intel.com>,
	Rahul Kumar <rahul1.kumar@intel.com>
Subject: Re: [PATCH v11 02/32] UefiCpuPkg/MpInitLib: move SEV specific routines in AmdSev.c
Date: Sun, 24 Oct 2021 18:45:52 -0500	[thread overview]
Message-ID: <ce4c7a34-4826-b16a-61aa-eff2ec57ca4f@amd.com> (raw)
In-Reply-To: <20211023041349.1263726-3-brijesh.singh@amd.com>

Hi Ray and Rahul,

Any comment on this patch ? If you are okay with it then can I get Ack
or R-b ?

-Brijesh

On 10/22/21 11:13 PM, Brijesh Singh wrote:
> BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3275
>
> Move all the SEV specific function in AmdSev.c.
>
> No functional change intended.
>
> Cc: Eric Dong <eric.dong@intel.com>
> Cc: Ray Ni <ray.ni@intel.com>
> Cc: Rahul Kumar <rahul1.kumar@intel.com>
> Cc: Michael Roth <michael.roth@amd.com>
> Cc: James Bottomley <jejb@linux.ibm.com>
> Cc: Min Xu <min.m.xu@intel.com>
> Cc: Jiewen Yao <jiewen.yao@intel.com>
> Cc: Tom Lendacky <thomas.lendacky@amd.com>
> Cc: Jordan Justen <jordan.l.justen@intel.com>
> Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
> Cc: Erdem Aktas <erdemaktas@google.com>
> Cc: Gerd Hoffmann <kraxel@redhat.com>
> Acked-by: Gerd Hoffmann <kraxel@redhat.com>
> Suggested-by: Jiewen Yao <Jiewen.yao@intel.com>
> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
> ---
>  UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf |   1 +
>  UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf |   1 +
>  UefiCpuPkg/Library/MpInitLib/MpLib.h          |  33 +++
>  UefiCpuPkg/Library/MpInitLib/AmdSev.c         | 239 ++++++++++++++++++
>  UefiCpuPkg/Library/MpInitLib/MpLib.c          | 218 +---------------
>  UefiCpuPkg/Library/MpInitLib/X64/AmdSev.nasm  | 119 +++++++++
>  UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm | 100 ++------
>  7 files changed, 413 insertions(+), 298 deletions(-)
>  create mode 100644 UefiCpuPkg/Library/MpInitLib/AmdSev.c
>  create mode 100644 UefiCpuPkg/Library/MpInitLib/X64/AmdSev.nasm
>
> diff --git a/UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf b/UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf
> index d34419c2a524..6e510aa89120 100644
> --- a/UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf
> +++ b/UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf
> @@ -28,6 +28,7 @@ [Sources.X64]
>    X64/MpFuncs.nasm
>  
>  [Sources.common]
> +  AmdSev.c
>    MpEqu.inc
>    DxeMpLib.c
>    MpLib.c
> diff --git a/UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf b/UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf
> index 36fcb96b5852..2cbd9b8b8acc 100644
> --- a/UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf
> +++ b/UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf
> @@ -28,6 +28,7 @@ [Sources.X64]
>    X64/MpFuncs.nasm
>  
>  [Sources.common]
> +  AmdSev.c
>    MpEqu.inc
>    PeiMpLib.c
>    MpLib.c
> diff --git a/UefiCpuPkg/Library/MpInitLib/MpLib.h b/UefiCpuPkg/Library/MpInitLib/MpLib.h
> index e88a5355c983..3d4446df8ce6 100644
> --- a/UefiCpuPkg/Library/MpInitLib/MpLib.h
> +++ b/UefiCpuPkg/Library/MpInitLib/MpLib.h
> @@ -34,6 +34,9 @@
>  #include <Library/PcdLib.h>
>  #include <Library/MicrocodeLib.h>
>  
> +#include <Register/Amd/Fam17Msr.h>
> +#include <Register/Amd/Ghcb.h>
> +
>  #include <Guid/MicrocodePatchHob.h>
>  
>  #define WAKEUP_AP_SIGNAL SIGNATURE_32 ('S', 'T', 'A', 'P')
> @@ -741,5 +744,35 @@ PlatformShadowMicrocode (
>    IN OUT CPU_MP_DATA             *CpuMpData
>    );
>  
> +/**
> +  Allocate the SEV-ES AP jump table buffer.
> +
> +  @param[in, out]  CpuMpData  The pointer to CPU MP Data structure.
> +**/
> +VOID
> +AllocateSevEsAPMemory (
> +  IN OUT CPU_MP_DATA          *CpuMpData
> +  );
> +
> +/**
> +  Program the SEV-ES AP jump table buffer.
> +
> +  @param[in]  SipiVector  The SIPI vector used for the AP Reset
> +**/
> +VOID
> +SetSevEsJumpTable (
> +  IN UINTN  SipiVector
> +  );
> +
> +/**
> +  The function puts the AP in halt loop.
> +
> +  @param[in]  CpuMpData  The pointer to CPU MP Data structure.
> +**/
> +VOID
> +SevEsPlaceApHlt (
> +  CPU_MP_DATA                *CpuMpData
> +  );
> +
>  #endif
>  
> diff --git a/UefiCpuPkg/Library/MpInitLib/AmdSev.c b/UefiCpuPkg/Library/MpInitLib/AmdSev.c
> new file mode 100644
> index 000000000000..7dbf117c2b71
> --- /dev/null
> +++ b/UefiCpuPkg/Library/MpInitLib/AmdSev.c
> @@ -0,0 +1,239 @@
> +/** @file
> +  CPU MP Initialize helper function for AMD SEV.
> +
> +  Copyright (c) 2021, AMD Inc. All rights reserved.<BR>
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#include "MpLib.h"
> +#include <Library/VmgExitLib.h>
> +
> +/**
> +  Get Protected mode code segment with 16-bit default addressing
> +  from current GDT table.
> +
> +  @return  Protected mode 16-bit code segment value.
> +**/
> +STATIC
> +UINT16
> +GetProtectedMode16CS (
> +  VOID
> +  )
> +{
> +  IA32_DESCRIPTOR          GdtrDesc;
> +  IA32_SEGMENT_DESCRIPTOR  *GdtEntry;
> +  UINTN                    GdtEntryCount;
> +  UINT16                   Index;
> +
> +  Index = (UINT16) -1;
> +  AsmReadGdtr (&GdtrDesc);
> +  GdtEntryCount = (GdtrDesc.Limit + 1) / sizeof (IA32_SEGMENT_DESCRIPTOR);
> +  GdtEntry = (IA32_SEGMENT_DESCRIPTOR *) GdtrDesc.Base;
> +  for (Index = 0; Index < GdtEntryCount; Index++) {
> +    if (GdtEntry->Bits.L == 0 &&
> +        GdtEntry->Bits.DB == 0 &&
> +        GdtEntry->Bits.Type > 8) {
> +      break;
> +    }
> +    GdtEntry++;
> +  }
> +  ASSERT (Index != GdtEntryCount);
> +  return Index * 8;
> +}
> +
> +/**
> +  Get Protected mode code segment with 32-bit default addressing
> +  from current GDT table.
> +
> +  @return  Protected mode 32-bit code segment value.
> +**/
> +STATIC
> +UINT16
> +GetProtectedMode32CS (
> +  VOID
> +  )
> +{
> +  IA32_DESCRIPTOR          GdtrDesc;
> +  IA32_SEGMENT_DESCRIPTOR  *GdtEntry;
> +  UINTN                    GdtEntryCount;
> +  UINT16                   Index;
> +
> +  Index = (UINT16) -1;
> +  AsmReadGdtr (&GdtrDesc);
> +  GdtEntryCount = (GdtrDesc.Limit + 1) / sizeof (IA32_SEGMENT_DESCRIPTOR);
> +  GdtEntry = (IA32_SEGMENT_DESCRIPTOR *) GdtrDesc.Base;
> +  for (Index = 0; Index < GdtEntryCount; Index++) {
> +    if (GdtEntry->Bits.L == 0 &&
> +        GdtEntry->Bits.DB == 1 &&
> +        GdtEntry->Bits.Type > 8) {
> +      break;
> +    }
> +    GdtEntry++;
> +  }
> +  ASSERT (Index != GdtEntryCount);
> +  return Index * 8;
> +}
> +
> +/**
> +  Reset an AP when in SEV-ES mode.
> +
> +  If successful, this function never returns.
> +
> +  @param[in] Ghcb                 Pointer to the GHCB
> +  @param[in] CpuMpData            Pointer to CPU MP Data
> +
> +**/
> +VOID
> +MpInitLibSevEsAPReset (
> +  IN GHCB                         *Ghcb,
> +  IN CPU_MP_DATA                  *CpuMpData
> +  )
> +{
> +  EFI_STATUS       Status;
> +  UINTN            ProcessorNumber;
> +  UINT16           Code16, Code32;
> +  AP_RESET         *APResetFn;
> +  UINTN            BufferStart;
> +  UINTN            StackStart;
> +
> +  Status = GetProcessorNumber (CpuMpData, &ProcessorNumber);
> +  ASSERT_EFI_ERROR (Status);
> +
> +  Code16 = GetProtectedMode16CS ();
> +  Code32 = GetProtectedMode32CS ();
> +
> +  if (CpuMpData->WakeupBufferHigh != 0) {
> +    APResetFn = (AP_RESET *) (CpuMpData->WakeupBufferHigh + CpuMpData->AddressMap.SwitchToRealNoNxOffset);
> +  } else {
> +    APResetFn = (AP_RESET *) (CpuMpData->MpCpuExchangeInfo->BufferStart + CpuMpData->AddressMap.SwitchToRealOffset);
> +  }
> +
> +  BufferStart = CpuMpData->MpCpuExchangeInfo->BufferStart;
> +  StackStart = CpuMpData->SevEsAPResetStackStart -
> +                 (AP_RESET_STACK_SIZE * ProcessorNumber);
> +
> +  //
> +  // This call never returns.
> +  //
> +  APResetFn (BufferStart, Code16, Code32, StackStart);
> +}
> +
> +/**
> +  Allocate the SEV-ES AP jump table buffer.
> +
> +  @param[in, out]  CpuMpData  The pointer to CPU MP Data structure.
> +**/
> +VOID
> +AllocateSevEsAPMemory (
> +  IN OUT CPU_MP_DATA          *CpuMpData
> +  )
> +{
> +  if (CpuMpData->SevEsAPBuffer == (UINTN) -1) {
> +    CpuMpData->SevEsAPBuffer =
> +      CpuMpData->SevEsIsEnabled ? GetSevEsAPMemory () : 0;
> +  }
> +}
> +
> +/**
> +  Program the SEV-ES AP jump table buffer.
> +
> +  @param[in]  SipiVector  The SIPI vector used for the AP Reset
> +**/
> +VOID
> +SetSevEsJumpTable (
> +  IN UINTN  SipiVector
> +  )
> +{
> +  SEV_ES_AP_JMP_FAR *JmpFar;
> +  UINT32            Offset, InsnByte;
> +  UINT8             LoNib, HiNib;
> +
> +  JmpFar = (SEV_ES_AP_JMP_FAR *) (UINTN) FixedPcdGet32 (PcdSevEsWorkAreaBase);
> +  ASSERT (JmpFar != NULL);
> +
> +  //
> +  // Obtain the address of the Segment/Rip location in the workarea.
> +  // This will be set to a value derived from the SIPI vector and will
> +  // be the memory address used for the far jump below.
> +  //
> +  Offset = FixedPcdGet32 (PcdSevEsWorkAreaBase);
> +  Offset += sizeof (JmpFar->InsnBuffer);
> +  LoNib = (UINT8) Offset;
> +  HiNib = (UINT8) (Offset >> 8);
> +
> +  //
> +  // Program the workarea (which is the initial AP boot address) with
> +  // far jump to the SIPI vector (where XX and YY represent the
> +  // address of where the SIPI vector is stored.
> +  //
> +  //   JMP FAR [CS:XXYY] => 2E FF 2E YY XX
> +  //
> +  InsnByte = 0;
> +  JmpFar->InsnBuffer[InsnByte++] = 0x2E;  // CS override prefix
> +  JmpFar->InsnBuffer[InsnByte++] = 0xFF;  // JMP (FAR)
> +  JmpFar->InsnBuffer[InsnByte++] = 0x2E;  // ModRM (JMP memory location)
> +  JmpFar->InsnBuffer[InsnByte++] = LoNib; // YY offset ...
> +  JmpFar->InsnBuffer[InsnByte++] = HiNib; // XX offset ...
> +
> +  //
> +  // Program the Segment/Rip based on the SIPI vector (always at least
> +  // 16-byte aligned, so Rip is set to 0).
> +  //
> +  JmpFar->Rip = 0;
> +  JmpFar->Segment = (UINT16) (SipiVector >> 4);
> +}
> +
> +/**
> +  The function puts the AP in halt loop.
> +
> +  @param[in]  CpuMpData  The pointer to CPU MP Data structure.
> +**/
> +VOID
> +SevEsPlaceApHlt (
> +  CPU_MP_DATA                *CpuMpData
> +  )
> +{
> +  MSR_SEV_ES_GHCB_REGISTER  Msr;
> +  GHCB                      *Ghcb;
> +  UINT64                    Status;
> +  BOOLEAN                   DoDecrement;
> +  BOOLEAN                   InterruptState;
> +
> +  DoDecrement = (BOOLEAN) (CpuMpData->InitFlag == ApInitConfig);
> +
> +  while (TRUE) {
> +    Msr.GhcbPhysicalAddress = AsmReadMsr64 (MSR_SEV_ES_GHCB);
> +    Ghcb = Msr.Ghcb;
> +
> +    VmgInit (Ghcb, &InterruptState);
> +
> +    if (DoDecrement) {
> +      DoDecrement = FALSE;
> +
> +      //
> +      // Perform the delayed decrement just before issuing the first
> +      // VMGEXIT with AP_RESET_HOLD.
> +      //
> +      InterlockedDecrement ((UINT32 *) &CpuMpData->MpCpuExchangeInfo->NumApsExecuting);
> +    }
> +
> +    Status = VmgExit (Ghcb, SVM_EXIT_AP_RESET_HOLD, 0, 0);
> +    if ((Status == 0) && (Ghcb->SaveArea.SwExitInfo2 != 0)) {
> +      VmgDone (Ghcb, InterruptState);
> +      break;
> +    }
> +
> +    VmgDone (Ghcb, InterruptState);
> +  }
> +
> +  //
> +  // Awakened in a new phase? Use the new CpuMpData
> +  //
> +  if (CpuMpData->NewCpuMpData != NULL) {
> +    CpuMpData = CpuMpData->NewCpuMpData;
> +  }
> +
> +  MpInitLibSevEsAPReset (Ghcb, CpuMpData);
> +}
> diff --git a/UefiCpuPkg/Library/MpInitLib/MpLib.c b/UefiCpuPkg/Library/MpInitLib/MpLib.c
> index b9a06747edbf..890945bc5994 100644
> --- a/UefiCpuPkg/Library/MpInitLib/MpLib.c
> +++ b/UefiCpuPkg/Library/MpInitLib/MpLib.c
> @@ -596,117 +596,6 @@ InitializeApData (
>    SetApState (&CpuMpData->CpuData[ProcessorNumber], CpuStateIdle);
>  }
>  
> -/**
> -  Get Protected mode code segment with 16-bit default addressing
> -  from current GDT table.
> -
> -  @return  Protected mode 16-bit code segment value.
> -**/
> -STATIC
> -UINT16
> -GetProtectedMode16CS (
> -  VOID
> -  )
> -{
> -  IA32_DESCRIPTOR          GdtrDesc;
> -  IA32_SEGMENT_DESCRIPTOR  *GdtEntry;
> -  UINTN                    GdtEntryCount;
> -  UINT16                   Index;
> -
> -  Index = (UINT16) -1;
> -  AsmReadGdtr (&GdtrDesc);
> -  GdtEntryCount = (GdtrDesc.Limit + 1) / sizeof (IA32_SEGMENT_DESCRIPTOR);
> -  GdtEntry = (IA32_SEGMENT_DESCRIPTOR *) GdtrDesc.Base;
> -  for (Index = 0; Index < GdtEntryCount; Index++) {
> -    if (GdtEntry->Bits.L == 0 &&
> -        GdtEntry->Bits.DB == 0 &&
> -        GdtEntry->Bits.Type > 8) {
> -      break;
> -    }
> -    GdtEntry++;
> -  }
> -  ASSERT (Index != GdtEntryCount);
> -  return Index * 8;
> -}
> -
> -/**
> -  Get Protected mode code segment with 32-bit default addressing
> -  from current GDT table.
> -
> -  @return  Protected mode 32-bit code segment value.
> -**/
> -STATIC
> -UINT16
> -GetProtectedMode32CS (
> -  VOID
> -  )
> -{
> -  IA32_DESCRIPTOR          GdtrDesc;
> -  IA32_SEGMENT_DESCRIPTOR  *GdtEntry;
> -  UINTN                    GdtEntryCount;
> -  UINT16                   Index;
> -
> -  Index = (UINT16) -1;
> -  AsmReadGdtr (&GdtrDesc);
> -  GdtEntryCount = (GdtrDesc.Limit + 1) / sizeof (IA32_SEGMENT_DESCRIPTOR);
> -  GdtEntry = (IA32_SEGMENT_DESCRIPTOR *) GdtrDesc.Base;
> -  for (Index = 0; Index < GdtEntryCount; Index++) {
> -    if (GdtEntry->Bits.L == 0 &&
> -        GdtEntry->Bits.DB == 1 &&
> -        GdtEntry->Bits.Type > 8) {
> -      break;
> -    }
> -    GdtEntry++;
> -  }
> -  ASSERT (Index != GdtEntryCount);
> -  return Index * 8;
> -}
> -
> -/**
> -  Reset an AP when in SEV-ES mode.
> -
> -  If successful, this function never returns.
> -
> -  @param[in] Ghcb                 Pointer to the GHCB
> -  @param[in] CpuMpData            Pointer to CPU MP Data
> -
> -**/
> -STATIC
> -VOID
> -MpInitLibSevEsAPReset (
> -  IN GHCB                         *Ghcb,
> -  IN CPU_MP_DATA                  *CpuMpData
> -  )
> -{
> -  EFI_STATUS       Status;
> -  UINTN            ProcessorNumber;
> -  UINT16           Code16, Code32;
> -  AP_RESET         *APResetFn;
> -  UINTN            BufferStart;
> -  UINTN            StackStart;
> -
> -  Status = GetProcessorNumber (CpuMpData, &ProcessorNumber);
> -  ASSERT_EFI_ERROR (Status);
> -
> -  Code16 = GetProtectedMode16CS ();
> -  Code32 = GetProtectedMode32CS ();
> -
> -  if (CpuMpData->WakeupBufferHigh != 0) {
> -    APResetFn = (AP_RESET *) (CpuMpData->WakeupBufferHigh + CpuMpData->AddressMap.SwitchToRealNoNxOffset);
> -  } else {
> -    APResetFn = (AP_RESET *) (CpuMpData->MpCpuExchangeInfo->BufferStart + CpuMpData->AddressMap.SwitchToRealOffset);
> -  }
> -
> -  BufferStart = CpuMpData->MpCpuExchangeInfo->BufferStart;
> -  StackStart = CpuMpData->SevEsAPResetStackStart -
> -                 (AP_RESET_STACK_SIZE * ProcessorNumber);
> -
> -  //
> -  // This call never returns.
> -  //
> -  APResetFn (BufferStart, Code16, Code32, StackStart);
> -}
> -
>  /**
>    This function will be called from AP reset code if BSP uses WakeUpAP.
>  
> @@ -884,47 +773,7 @@ ApWakeupFunction (
>        while (TRUE) {
>          DisableInterrupts ();
>          if (CpuMpData->SevEsIsEnabled) {
> -          MSR_SEV_ES_GHCB_REGISTER  Msr;
> -          GHCB                      *Ghcb;
> -          UINT64                    Status;
> -          BOOLEAN                   DoDecrement;
> -          BOOLEAN                   InterruptState;
> -
> -          DoDecrement = (BOOLEAN) (CpuMpData->InitFlag == ApInitConfig);
> -
> -          while (TRUE) {
> -            Msr.GhcbPhysicalAddress = AsmReadMsr64 (MSR_SEV_ES_GHCB);
> -            Ghcb = Msr.Ghcb;
> -
> -            VmgInit (Ghcb, &InterruptState);
> -
> -            if (DoDecrement) {
> -              DoDecrement = FALSE;
> -
> -              //
> -              // Perform the delayed decrement just before issuing the first
> -              // VMGEXIT with AP_RESET_HOLD.
> -              //
> -              InterlockedDecrement ((UINT32 *) &CpuMpData->MpCpuExchangeInfo->NumApsExecuting);
> -            }
> -
> -            Status = VmgExit (Ghcb, SVM_EXIT_AP_RESET_HOLD, 0, 0);
> -            if ((Status == 0) && (Ghcb->SaveArea.SwExitInfo2 != 0)) {
> -              VmgDone (Ghcb, InterruptState);
> -              break;
> -            }
> -
> -            VmgDone (Ghcb, InterruptState);
> -          }
> -
> -          //
> -          // Awakened in a new phase? Use the new CpuMpData
> -          //
> -          if (CpuMpData->NewCpuMpData != NULL) {
> -            CpuMpData = CpuMpData->NewCpuMpData;
> -          }
> -
> -          MpInitLibSevEsAPReset (Ghcb, CpuMpData);
> +          SevEsPlaceApHlt (CpuMpData);
>          } else {
>            CpuSleep ();
>          }
> @@ -1252,71 +1101,6 @@ FreeResetVector (
>    }
>  }
>  
> -/**
> -  Allocate the SEV-ES AP jump table buffer.
> -
> -  @param[in, out]  CpuMpData  The pointer to CPU MP Data structure.
> -**/
> -VOID
> -AllocateSevEsAPMemory (
> -  IN OUT CPU_MP_DATA          *CpuMpData
> -  )
> -{
> -  if (CpuMpData->SevEsAPBuffer == (UINTN) -1) {
> -    CpuMpData->SevEsAPBuffer =
> -      CpuMpData->SevEsIsEnabled ? GetSevEsAPMemory () : 0;
> -  }
> -}
> -
> -/**
> -  Program the SEV-ES AP jump table buffer.
> -
> -  @param[in]  SipiVector  The SIPI vector used for the AP Reset
> -**/
> -VOID
> -SetSevEsJumpTable (
> -  IN UINTN  SipiVector
> -  )
> -{
> -  SEV_ES_AP_JMP_FAR *JmpFar;
> -  UINT32            Offset, InsnByte;
> -  UINT8             LoNib, HiNib;
> -
> -  JmpFar = (SEV_ES_AP_JMP_FAR *) (UINTN) FixedPcdGet32 (PcdSevEsWorkAreaBase);
> -  ASSERT (JmpFar != NULL);
> -
> -  //
> -  // Obtain the address of the Segment/Rip location in the workarea.
> -  // This will be set to a value derived from the SIPI vector and will
> -  // be the memory address used for the far jump below.
> -  //
> -  Offset = FixedPcdGet32 (PcdSevEsWorkAreaBase);
> -  Offset += sizeof (JmpFar->InsnBuffer);
> -  LoNib = (UINT8) Offset;
> -  HiNib = (UINT8) (Offset >> 8);
> -
> -  //
> -  // Program the workarea (which is the initial AP boot address) with
> -  // far jump to the SIPI vector (where XX and YY represent the
> -  // address of where the SIPI vector is stored.
> -  //
> -  //   JMP FAR [CS:XXYY] => 2E FF 2E YY XX
> -  //
> -  InsnByte = 0;
> -  JmpFar->InsnBuffer[InsnByte++] = 0x2E;  // CS override prefix
> -  JmpFar->InsnBuffer[InsnByte++] = 0xFF;  // JMP (FAR)
> -  JmpFar->InsnBuffer[InsnByte++] = 0x2E;  // ModRM (JMP memory location)
> -  JmpFar->InsnBuffer[InsnByte++] = LoNib; // YY offset ...
> -  JmpFar->InsnBuffer[InsnByte++] = HiNib; // XX offset ...
> -
> -  //
> -  // Program the Segment/Rip based on the SIPI vector (always at least
> -  // 16-byte aligned, so Rip is set to 0).
> -  //
> -  JmpFar->Rip = 0;
> -  JmpFar->Segment = (UINT16) (SipiVector >> 4);
> -}
> -
>  /**
>    This function will be called by BSP to wakeup AP.
>  
> diff --git a/UefiCpuPkg/Library/MpInitLib/X64/AmdSev.nasm b/UefiCpuPkg/Library/MpInitLib/X64/AmdSev.nasm
> new file mode 100644
> index 000000000000..0ccafe25eca4
> --- /dev/null
> +++ b/UefiCpuPkg/Library/MpInitLib/X64/AmdSev.nasm
> @@ -0,0 +1,119 @@
> +;------------------------------------------------------------------------------ ;
> +; Copyright (c) 2021, AMD Inc. All rights reserved.<BR>
> +; SPDX-License-Identifier: BSD-2-Clause-Patent
> +;
> +; Module Name:
> +;
> +;   AmdSev.nasm
> +;
> +; Abstract:
> +;
> +;   This provides helper used by the MpFunc.nasm. If AMD SEV-ES is active
> +;   then helpers perform the additional setups (such as GHCB).
> +;
> +;-------------------------------------------------------------------------------
> +
> +%define SIZE_4KB    0x1000
> +
> +;
> +; The function checks whether SEV-ES is enabled, if enabled
> +; then setup the GHCB page.
> +;
> +SevEsSetupGhcb:
> +    lea        edi, [esi + MP_CPU_EXCHANGE_INFO_FIELD (SevEsIsEnabled)]
> +    cmp        byte [edi], 1        ; SevEsIsEnabled
> +    jne        SevEsSetupGhcbExit
> +
> +    ;
> +    ; program GHCB
> +    ;   Each page after the GHCB is a per-CPU page, so the calculation programs
> +    ;   a GHCB to be every 8KB.
> +    ;
> +    mov        eax, SIZE_4KB
> +    shl        eax, 1                            ; EAX = SIZE_4K * 2
> +    mov        ecx, ebx
> +    mul        ecx                               ; EAX = SIZE_4K * 2 * CpuNumber
> +    mov        edi, esi
> +    add        edi, MP_CPU_EXCHANGE_INFO_FIELD (GhcbBase)
> +    add        rax, qword [edi]
> +    mov        rdx, rax
> +    shr        rdx, 32
> +    mov        rcx, 0xc0010130
> +    wrmsr
> +
> +SevEsSetupGhcbExit:
> +    OneTimeCallRet    SevEsSetupGhcb
> +
> +;
> +; The function checks whether SEV-ES is enabled, if enabled, use
> +; the GHCB
> +;
> +SevEsGetApicId:
> +    lea        edi, [esi + MP_CPU_EXCHANGE_INFO_FIELD (SevEsIsEnabled)]
> +    cmp        byte [edi], 1        ; SevEsIsEnabled
> +    jne        SevEsGetApicIdExit
> +
> +    ;
> +    ; Since we don't have a stack yet, we can't take a #VC
> +    ; exception. Use the GHCB protocol to perform the CPUID
> +    ; calls.
> +    ;
> +    mov        rcx, 0xc0010130
> +    rdmsr
> +    shl        rdx, 32
> +    or         rax, rdx
> +    mov        rdi, rax             ; RDI now holds the original GHCB GPA
> +
> +    mov        rdx, 0               ; CPUID function 0
> +    mov        rax, 0               ; RAX register requested
> +    or         rax, 4
> +    wrmsr
> +    rep vmmcall
> +    rdmsr
> +    cmp        edx, 0bh
> +    jb         NoX2ApicSevEs        ; CPUID level below CPUID_EXTENDED_TOPOLOGY
> +
> +    mov        rdx, 0bh             ; CPUID function 0x0b
> +    mov        rax, 040000000h      ; RBX register requested
> +    or         rax, 4
> +    wrmsr
> +    rep vmmcall
> +    rdmsr
> +    test       edx, 0ffffh
> +    jz         NoX2ApicSevEs        ; CPUID.0BH:EBX[15:0] is zero
> +
> +    mov        rdx, 0bh             ; CPUID function 0x0b
> +    mov        rax, 0c0000000h      ; RDX register requested
> +    or         rax, 4
> +    wrmsr
> +    rep vmmcall
> +    rdmsr
> +
> +    ; Processor is x2APIC capable; 32-bit x2APIC ID is now in EDX
> +    jmp        RestoreGhcb
> +
> +NoX2ApicSevEs:
> +    ; Processor is not x2APIC capable, so get 8-bit APIC ID
> +    mov        rdx, 1               ; CPUID function 1
> +    mov        rax, 040000000h      ; RBX register requested
> +    or         rax, 4
> +    wrmsr
> +    rep vmmcall
> +    rdmsr
> +    shr        edx, 24
> +
> +RestoreGhcb:
> +    mov        rbx, rdx             ; Save x2APIC/APIC ID
> +
> +    mov        rdx, rdi             ; RDI holds the saved GHCB GPA
> +    shr        rdx, 32
> +    mov        eax, edi
> +    wrmsr
> +
> +    mov        rdx, rbx
> +
> +    ; x2APIC ID or APIC ID is in EDX
> +    jmp        GetProcessorNumber
> +
> +SevEsGetApicIdExit:
> +    OneTimeCallRet    SevEsGetApicId
> diff --git a/UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm b/UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm
> index 50df802d1fca..f7f2937fafad 100644
> --- a/UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm
> +++ b/UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm
> @@ -15,6 +15,15 @@
>  %include "MpEqu.inc"
>  extern ASM_PFX(InitializeFloatingPointUnits)
>  
> +%macro  OneTimeCall 1
> +    jmp     %1
> +%1 %+ OneTimerCallReturn:
> +%endmacro
> +
> +%macro  OneTimeCallRet 1
> +    jmp     %1 %+ OneTimerCallReturn
> +%endmacro
> +
>  DEFAULT REL
>  
>  SECTION .text
> @@ -144,6 +153,12 @@ SkipEnable5LevelPaging:
>      jmp far    [edi]
>  
>  BITS 64
> +
> +;
> +; Required for the AMD SEV helper functions
> +;
> +%include "AmdSev.nasm"
> +
>  LongModeStart:
>      mov        esi, ebx
>      lea        edi, [esi + MP_CPU_EXCHANGE_INFO_FIELD (InitFlag)]
> @@ -175,94 +190,17 @@ LongModeStart:
>      add        rax, qword [edi]
>      mov        rsp, rax
>  
> -    lea        edi, [esi + MP_CPU_EXCHANGE_INFO_FIELD (SevEsIsEnabled)]
> -    cmp        byte [edi], 1        ; SevEsIsEnabled
> -    jne        CProcedureInvoke
> -
>      ;
> -    ; program GHCB
> -    ;   Each page after the GHCB is a per-CPU page, so the calculation programs
> -    ;   a GHCB to be every 8KB.
> +    ;  Setup the GHCB when AMD SEV-ES active.
>      ;
> -    mov        eax, SIZE_4KB
> -    shl        eax, 1                            ; EAX = SIZE_4K * 2
> -    mov        ecx, ebx
> -    mul        ecx                               ; EAX = SIZE_4K * 2 * CpuNumber
> -    mov        edi, esi
> -    add        edi, MP_CPU_EXCHANGE_INFO_FIELD (GhcbBase)
> -    add        rax, qword [edi]
> -    mov        rdx, rax
> -    shr        rdx, 32
> -    mov        rcx, 0xc0010130
> -    wrmsr
> +    OneTimeCall SevEsSetupGhcb
>      jmp        CProcedureInvoke
>  
>  GetApicId:
> -    lea        edi, [esi + MP_CPU_EXCHANGE_INFO_FIELD (SevEsIsEnabled)]
> -    cmp        byte [edi], 1        ; SevEsIsEnabled
> -    jne        DoCpuid
> -
>      ;
> -    ; Since we don't have a stack yet, we can't take a #VC
> -    ; exception. Use the GHCB protocol to perform the CPUID
> -    ; calls.
> +    ; Use the GHCB protocol to get the ApicId when SEV-ES is active.
>      ;
> -    mov        rcx, 0xc0010130
> -    rdmsr
> -    shl        rdx, 32
> -    or         rax, rdx
> -    mov        rdi, rax             ; RDI now holds the original GHCB GPA
> -
> -    mov        rdx, 0               ; CPUID function 0
> -    mov        rax, 0               ; RAX register requested
> -    or         rax, 4
> -    wrmsr
> -    rep vmmcall
> -    rdmsr
> -    cmp        edx, 0bh
> -    jb         NoX2ApicSevEs        ; CPUID level below CPUID_EXTENDED_TOPOLOGY
> -
> -    mov        rdx, 0bh             ; CPUID function 0x0b
> -    mov        rax, 040000000h      ; RBX register requested
> -    or         rax, 4
> -    wrmsr
> -    rep vmmcall
> -    rdmsr
> -    test       edx, 0ffffh
> -    jz         NoX2ApicSevEs        ; CPUID.0BH:EBX[15:0] is zero
> -
> -    mov        rdx, 0bh             ; CPUID function 0x0b
> -    mov        rax, 0c0000000h      ; RDX register requested
> -    or         rax, 4
> -    wrmsr
> -    rep vmmcall
> -    rdmsr
> -
> -    ; Processor is x2APIC capable; 32-bit x2APIC ID is now in EDX
> -    jmp        RestoreGhcb
> -
> -NoX2ApicSevEs:
> -    ; Processor is not x2APIC capable, so get 8-bit APIC ID
> -    mov        rdx, 1               ; CPUID function 1
> -    mov        rax, 040000000h      ; RBX register requested
> -    or         rax, 4
> -    wrmsr
> -    rep vmmcall
> -    rdmsr
> -    shr        edx, 24
> -
> -RestoreGhcb:
> -    mov        rbx, rdx             ; Save x2APIC/APIC ID
> -
> -    mov        rdx, rdi             ; RDI holds the saved GHCB GPA
> -    shr        rdx, 32
> -    mov        eax, edi
> -    wrmsr
> -
> -    mov        rdx, rbx
> -
> -    ; x2APIC ID or APIC ID is in EDX
> -    jmp        GetProcessorNumber
> +    OneTimeCall SevEsGetApicId
>  
>  DoCpuid:
>      mov        eax, 0

  reply	other threads:[~2021-10-24 23:46 UTC|newest]

Thread overview: 51+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-10-23  4:13 [PATCH v11 00/32] Add AMD Secure Nested Paging (SEV-SNP) support Brijesh Singh
2021-10-23  4:13 ` [PATCH v11 01/32] OvmfPkg/SecMain: move SEV specific routines in AmdSev.c Brijesh Singh
2021-10-23  4:13 ` [PATCH v11 02/32] UefiCpuPkg/MpInitLib: " Brijesh Singh
2021-10-24 23:45   ` Brijesh Singh [this message]
2021-11-04 13:53     ` Yao, Jiewen
2021-10-23  4:13 ` [PATCH v11 03/32] OvmfPkg/ResetVector: move clearing GHCB in SecMain Brijesh Singh
2021-10-23  4:13 ` [PATCH v11 04/32] OvmfPkg/ResetVector: introduce SEV metadata descriptor for VMM use Brijesh Singh
2021-10-23  4:13 ` [PATCH v11 05/32] OvmfPkg: reserve SNP secrets page Brijesh Singh
2021-10-23  4:13 ` [PATCH v11 06/32] OvmfPkg: reserve CPUID page Brijesh Singh
2021-10-23  4:13 ` [PATCH v11 07/32] OvmfPkg/ResetVector: pre-validate the data pages used in SEC phase Brijesh Singh
2021-10-23  4:13 ` [PATCH v11 08/32] OvmfPkg/ResetVector: use SEV-SNP-validated CPUID values Brijesh Singh
2021-10-23  4:13 ` [PATCH v11 09/32] OvmfPkg/MemEncryptSevLib: add MemEncryptSevSnpEnabled() Brijesh Singh
2021-10-23  4:13 ` [PATCH v11 10/32] OvmfPkg/SecMain: register GHCB gpa for the SEV-SNP guest Brijesh Singh
2021-10-23  4:13 ` [PATCH v11 11/32] OvmfPkg/VmgExitLib: use SEV-SNP-validated CPUID values Brijesh Singh
2021-10-23  4:13 ` [PATCH v11 12/32] OvmfPkg/PlatformPei: register GHCB gpa for the SEV-SNP guest Brijesh Singh
2021-10-23  4:13 ` [PATCH v11 13/32] OvmfPkg/AmdSevDxe: do not use extended PCI config space Brijesh Singh
2021-10-23  4:13 ` [PATCH v11 14/32] OvmfPkg/MemEncryptSevLib: add support to validate system RAM Brijesh Singh
2021-10-23  4:13 ` [PATCH v11 15/32] OvmfPkg/MemEncryptSevLib: add function to check the VMPL0 Brijesh Singh
2021-10-23  4:13 ` [PATCH v11 16/32] OvmfPkg/BaseMemEncryptSevLib: skip the pre-validated system RAM Brijesh Singh
2021-10-23  4:13 ` [PATCH v11 17/32] OvmfPkg/MemEncryptSevLib: add support to validate > 4GB memory in PEI phase Brijesh Singh
2021-10-23  4:13 ` [PATCH v11 18/32] OvmfPkg/SecMain: validate the memory used for decompressing Fv Brijesh Singh
2021-10-23  4:13 ` [PATCH v11 19/32] OvmfPkg/PlatformPei: validate the system RAM when SNP is active Brijesh Singh
2021-10-23  4:13 ` [PATCH v11 20/32] UefiCpuPkg: Define ConfidentialComputingGuestAttr Brijesh Singh
2021-10-24 23:44   ` Brijesh Singh
2021-10-25  7:22   ` [edk2-devel] " Min Xu
2021-10-25 13:57     ` Brijesh Singh
2021-10-23  4:13 ` [PATCH v11 21/32] OvmfPkg/PlatformPei: set PcdConfidentialComputingAttr when SEV is active Brijesh Singh
2021-10-23  4:13 ` [PATCH v11 22/32] UefiCpuPkg/MpInitLib: use PcdConfidentialComputingAttr to check SEV status Brijesh Singh
2021-10-23  4:13 ` [PATCH v11 23/32] UefiCpuPkg: add PcdGhcbHypervisorFeatures Brijesh Singh
2021-10-23  4:13 ` [PATCH v11 24/32] OvmfPkg/PlatformPei: set the Hypervisor Features PCD Brijesh Singh
2021-10-23  4:13 ` [PATCH v11 25/32] MdePkg/GHCB: increase the GHCB protocol max version Brijesh Singh
2021-10-23  4:13 ` [PATCH v11 26/32] UefiCpuPkg/MpLib: add support to register GHCB GPA when SEV-SNP is enabled Brijesh Singh
2021-10-23  4:13 ` [PATCH v11 27/32] UefiCpuPkg/MpInitLib: use BSP to do extended topology check Brijesh Singh
2021-10-23  4:13 ` [PATCH v11 28/32] OvmfPkg/MemEncryptSevLib: change the page state in the RMP table Brijesh Singh
2021-10-23  4:13 ` [PATCH v11 29/32] OvmfPkg/MemEncryptSevLib: skip page state change for Mmio address Brijesh Singh
2021-10-23  4:13 ` [PATCH v11 30/32] OvmfPkg/PlatformPei: mark cpuid and secrets memory reserved in EFI map Brijesh Singh
2021-10-23  4:13 ` [PATCH v11 31/32] OvmfPkg/AmdSev: expose the SNP reserved pages through configuration table Brijesh Singh
2021-10-23  4:13 ` [PATCH v11 32/32] UefiCpuPkg/MpInitLib: Use SEV-SNP AP Creation NAE event to launch APs Brijesh Singh
2021-10-24  1:46 ` [PATCH v11 00/32] Add AMD Secure Nested Paging (SEV-SNP) support Yao, Jiewen
2021-10-24  4:36   ` [edk2-devel] " Brijesh Singh
2021-10-24 23:54   ` Brijesh Singh
2021-10-29 12:26     ` Yao, Jiewen
2021-10-29 14:52       ` Brijesh Singh
2021-10-31 21:40         ` Brijesh Singh
     [not found]         ` <16B33B74BAC60F9D.13000@groups.io>
2021-11-08  2:10           ` Brijesh Singh
2021-11-08  2:14             ` Yao, Jiewen
2021-11-08  2:49               ` Brijesh Singh
2021-11-08  2:54                 ` Yao, Jiewen
     [not found] ` <16B08DB9AF0DA9D0.23504@groups.io>
2021-10-24 23:43   ` [edk2-devel] [PATCH v11 32/32] UefiCpuPkg/MpInitLib: Use SEV-SNP AP Creation NAE event to launch APs Brijesh Singh
     [not found] ` <16B08DB907104617.16488@groups.io>
2021-10-24 23:43   ` [edk2-devel] [PATCH v11 27/32] UefiCpuPkg/MpInitLib: use BSP to do extended topology check Brijesh Singh
     [not found] ` <16B08DB7BBA673AC.26581@groups.io>
2021-10-24 23:44   ` [edk2-devel] [PATCH v11 23/32] UefiCpuPkg: add PcdGhcbHypervisorFeatures Brijesh Singh

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=ce4c7a34-4826-b16a-61aa-eff2ec57ca4f@amd.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