[edk2-devel] [PATCH v2 4/6] UefiCpuPkg: Implements SmmSmramSaveStateLib library class

Chang, Abner via groups.io abner.chang=amd.com at groups.io
Sun Jan 15 04:45:10 UTC 2023


[AMD Official Use Only - General]

According to the section 4.2.3 in edk2 c coding standard spec in below link, the processor vendor directory must be under the processor arch directory. We use vendor directory because the different implementations of the same processor arch.
https://tianocore-docs.github.io/edk2-CCodingStandardsSpecification/draft/edk2-CCodingStandardsSpecification-draft.pdf
So for this case, we can just have AmdSmramSaveState.c under SmramSaveStateLib\ according to the file naming defined in 4.3.5.4 because this library is only for X86 platform. 

After this patch set is reviewed and merged, we should have another patch set to update PiSmmCpuDxeSmm to use this library for SMM register access, remove the one in SmmCpuFeaturelib. Also update OVMF to use SmmSmramSaveStateLib. Migration SmmSaveState.c under PiSmmCpuDxeSmm to SmmSmramSaveStateLib for Intel implementation.

Other comments in below, 

> -----Original Message-----
> From: devel at edk2.groups.io <devel at edk2.groups.io> On Behalf Of Abdul
> Lateef Attar via groups.io
> Sent: Wednesday, January 11, 2023 2:16 PM
> To: devel at edk2.groups.io
> Cc: Attar, AbdulLateef (Abdul Lateef) <AbdulLateef.Attar at amd.com>;
> Grimes, Paul <Paul.Grimes at amd.com>; Kirkendall, Garrett
> <Garrett.Kirkendall at amd.com>; Chang, Abner <Abner.Chang at amd.com>;
> Eric Dong <eric.dong at intel.com>; Ray Ni <ray.ni at intel.com>; Rahul Kumar
> <rahul1.kumar at intel.com>; Gerd Hoffmann <kraxel at redhat.com>; Attar,
> AbdulLateef (Abdul Lateef) <AbdulLateef.Attar at amd.com>
> Subject: [edk2-devel] [PATCH v2 4/6] UefiCpuPkg: Implements
> SmmSmramSaveStateLib library class
> 
> Caution: This message originated from an External Source. Use proper
> caution when opening attachments, clicking links, or responding.
> 
> 
> From: Abdul Lateef Attar <AbdulLateef.Attar at amd.com>
> 
> BZ:
> https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fbugz
> illa.tianocore.org%2Fshow_bug.cgi%3Fid%3D4182&data=05%7C01%7Cabner.
> chang%40amd.com%7C21622ff06cd949cc7e1608daf39b82a2%7C3dd8961fe48
> 84e608e11a82d994e183d%7C0%7C0%7C638090146492954852%7CUnknown%
> 7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haW
> wiLCJXVCI6Mn0%3D%7C3000%7C%7C%7C&sdata=QgHzNdcBkpCNbjGLPfx0L
> Em6ECHYowjuSryyNiWf0ww%3D&reserved=0
> 
> Implements SmmSmramSaveStateLib Library class for AMD cpu family.
> 
> Cc: Paul Grimes <paul.grimes at amd.com>
> Cc: Garrett Kirkendall <garrett.kirkendall at amd.com>
> Cc: Abner Chang <abner.chang at amd.com>
> Cc: Eric Dong <eric.dong at intel.com>
> Cc: Ray Ni <ray.ni at intel.com>
> Cc: Rahul Kumar <rahul1.kumar at intel.com>
> Cc: Gerd Hoffmann <kraxel at redhat.com>
> 
> Signed-off-by: Abdul Lateef Attar <abdattar at amd.com>
> ---
>  UefiCpuPkg/UefiCpuPkg.dsc                     |   3 +
>  .../AmdSmmSmramSaveStateLib.inf               |  28 ++
>  .../SmmSmramSaveStateLib/SmramSaveState.h     | 102 ++++++
>  .../SmmSmramSaveStateLib/Amd/SmramSaveState.c | 318
> ++++++++++++++++++
>  .../SmramSaveStateCommon.c                    | 124 +++++++
>  5 files changed, 575 insertions(+)
>  create mode 100644
> UefiCpuPkg/Library/SmmSmramSaveStateLib/AmdSmmSmramSaveStateLib.
> inf
>  create mode 100644
> UefiCpuPkg/Library/SmmSmramSaveStateLib/SmramSaveState.h
>  create mode 100644
> UefiCpuPkg/Library/SmmSmramSaveStateLib/Amd/SmramSaveState.c
>  create mode 100644
> UefiCpuPkg/Library/SmmSmramSaveStateLib/SmramSaveStateCommon.c
> 
> diff --git a/UefiCpuPkg/UefiCpuPkg.dsc b/UefiCpuPkg/UefiCpuPkg.dsc index
> f9a46089d2c7..99f7532ce00b 100644
> --- a/UefiCpuPkg/UefiCpuPkg.dsc
> +++ b/UefiCpuPkg/UefiCpuPkg.dsc
> @@ -2,6 +2,7 @@
>  #  UefiCpuPkg Package
> 
>  #
> 
>  #  Copyright (c) 2007 - 2022, Intel Corporation. All rights reserved.<BR>
> 
> +#  Copyright (C) 2023 Advanced Micro Devices, Inc. All rights
> +reserved.<BR>
> 
>  #
> 
>  #  SPDX-License-Identifier: BSD-2-Clause-Patent
> 
>  #
> 
> @@ -104,6 +105,7 @@ [LibraryClasses.common.DXE_SMM_DRIVER]
> 
> MemoryAllocationLib|MdePkg/Library/SmmMemoryAllocationLib/SmmMe
> moryAllocationLib.inf
> 
>    HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
> 
> 
> CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/Smm
> CpuExceptionHandlerLib.inf
> 
> +
> +
> SmmSmramSaveStateLib|UefiCpuPkg/Library/SmmSmramSaveStateLib/Am
> dSmmSmr
> + amSaveStateLib.inf
> 
> 
> 
>  [LibraryClasses.common.MM_STANDALONE]
> 
> 
> MmServicesTableLib|MdePkg/Library/StandaloneMmServicesTableLib/Stan
> daloneMmServicesTableLib.inf
> 
> @@ -191,6 +193,7 @@ [Components.IA32, Components.X64]
>      <LibraryClasses>
> 
> 
> UnitTestResultReportLib|UnitTestFrameworkPkg/Library/UnitTestResultRep
> ortLib/UnitTestResultReportLibConOut.inf
> 
>    }
> 
> +
> UefiCpuPkg/Library/SmmSmramSaveStateLib/AmdSmmSmramSaveStateLib.
> inf
> 
> 
> 
>  [Components.X64]
> 
> 
> UefiCpuPkg/Library/CpuExceptionHandlerLib/UnitTest/DxeCpuExceptionHan
> dlerLibUnitTest.inf
> 
> diff --git
> a/UefiCpuPkg/Library/SmmSmramSaveStateLib/AmdSmmSmramSaveStateLi
> b.inf
> b/UefiCpuPkg/Library/SmmSmramSaveStateLib/AmdSmmSmramSaveStateLi
> b.inf
> new file mode 100644
> index 000000000000..463e4c9331be
> --- /dev/null
> +++
> b/UefiCpuPkg/Library/SmmSmramSaveStateLib/AmdSmmSmramSaveStateLi
> b.in
> +++ f
> @@ -0,0 +1,28 @@
> +## @file
> 
> +# SMM Smram save state service lib.
> 
> +#
> 
> +# This is SMM Smram save state service lib that provide service to read
> +and
> 
> +# save savestate area registers.
> 
> +#
> 
> +# Copyright (C) 2023 Advanced Micro Devices, Inc. All rights
> +reserved.<BR>
> 
> +#
> 
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> +#
> 
> +##
> 
> +
> 
> +[Defines]
> 
> +  INF_VERSION                    = 1.29
> 
> +  BASE_NAME                      = AmdSmmSmramSaveStateLib
> 
> +  FILE_GUID                      = FB7D0A60-E8D4-4EFA-90AA-B357BC569879
> 
> +  MODULE_TYPE                    = DXE_SMM_DRIVER
> 
> +  VERSION_STRING                 = 1.0
> 
> +  LIBRARY_CLASS                  = SmmSmramSaveStateLib
> 
> +
> 
> +[Sources]
> 
> +  SmramSaveState.h
> 
> +  SmramSaveStateCommon.c
> 
> +  Amd/SmramSaveState.c
> 
> +
> 
> +[Packages]
> 
> +  MdePkg/MdePkg.dec
> 
> +  UefiCpuPkg/UefiCpuPkg.dec
> 
> diff --git a/UefiCpuPkg/Library/SmmSmramSaveStateLib/SmramSaveState.h
> b/UefiCpuPkg/Library/SmmSmramSaveStateLib/SmramSaveState.h
> new file mode 100644
> index 000000000000..c55ae004e016
> --- /dev/null
> +++ b/UefiCpuPkg/Library/SmmSmramSaveStateLib/SmramSaveState.h
> @@ -0,0 +1,102 @@
> +/** @file
> 
> +  SMRAM Save State Map header file.
> 
> +
> 
> +  Copyright (c) 2010 - 2019, Intel Corporation. All rights
> + reserved.<BR>
> 
> +  Copyright (C) 2023 Advanced Micro Devices, Inc. All rights
> + reserved.<BR>
> 
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> +
> 
> +**/
> 
> +
> 
> +#ifndef SMRAM_SAVESTATE_H_
> 
> +#define SMRAM_SAVESTATE_H_
> 
> +
> 
> +#include <Uefi/UefiBaseType.h>
> 
> +#include <Protocol/SmmCpu.h>
> 
> +#include <Library/DebugLib.h>
> 
> +#include <Library/SmmSmramSaveStateLib.h>
> 
> +#include <Library/SmmServicesTableLib.h>
> 
> +#include <Library/BaseMemoryLib.h>
> 
> +
> 
> +// EFER register LMA bit
> 
> +#define LMA  BIT10
> 
> +
> 
> +// Macro used to simplify the lookup table entries of type
> +CPU_SMM_SAVE_STATE_REGISTER_RANGE
> 
> +#define SMM_REGISTER_RANGE(Start, End)  { Start, End, End - Start + 1 }
> 
> +
> 
> +#define SMM_SAVE_STATE_REGISTER_MAX_INDEX  2
> 
> +
> 
> +// Structure used to describe a range of registers
> 
> +typedef struct {
> 
> +  EFI_SMM_SAVE_STATE_REGISTER    Start;
> 
> +  EFI_SMM_SAVE_STATE_REGISTER    End;
> 
> +  UINTN                          Length;
> 
> +} CPU_SMM_SAVE_STATE_REGISTER_RANGE;
> 
> +
> 
> +// Structure used to build a lookup table to retrieve the widths and
> +offsets
> 
> +// associated with each supported EFI_SMM_SAVE_STATE_REGISTER value
> 
> +
> 
> +typedef struct {
> 
> +  UINT8      Width32;
> 
> +  UINT8      Width64;
> 
> +  UINT16     Offset32;
> 
> +  UINT16     Offset64Lo;
> 
> +  UINT16     Offset64Hi;
> 
> +  BOOLEAN    Writeable;
> 
> +} CPU_SMM_SAVE_STATE_LOOKUP_ENTRY;
> 
> +
> 
> +/**
> 
> +  Returns LMA value of the Processor.
> 
> +
> 
> +  @param[in]  VOID
> 
> +
> 
> +  @retval     UINT8 returns LMA bit value.
> 
> +**/
> 
> +UINT8
> 
> +EFIAPI
> 
> +SmramSaveStateGetRegisterLma (
> 
> +  VOID
> 
> +  );
> 
> +
> 
> +/**
> 
> +  Read information from the CPU save state.
> 
> +
> 
> +  @param  Register  Specifies the CPU register to read form the save state.
> 
> +
> 
> +  @retval 0   Register is not valid
> 
> +  @retval >0  Index into mSmmSmramCpuWidthOffset[] associated with
> + Register
> 
> +
> 
> +**/
> 
> +UINTN
> 
> +EFIAPI
> 
> +SmramSaveStateGetRegisterIndex (
> 
> +  IN EFI_SMM_SAVE_STATE_REGISTER  Register
> 
> +  );
> 
> +
> 
> +/**
> 
> +  Read a CPU Save State register on the target processor.
> 
> +
> 
> +  This function abstracts the differences that whether the CPU Save
> + State register is in the
> 
> +  IA32 CPU Save State Map or X64 CPU Save State Map.
> 
> +
> 
> +  This function supports reading a CPU Save State register in SMBase
> relocation handler.
> 
> +
> 
> +  @param[in]  CpuIndex       Specifies the zero-based index of the CPU save
> state.
> 
> +  @param[in]  RegisterIndex  Index into mSmmSmramCpuWidthOffset[]
> look up table.
> 
> +  @param[in]  Width          The number of bytes to read from the CPU save
> state.
> 
> +  @param[out] Buffer         Upon return, this holds the CPU register value
> read from the save state.
> 
> +
> 
> +  @retval EFI_SUCCESS           The register was read from Save State.
> 
> +  @retval EFI_NOT_FOUND         The register is not defined for the Save
> State of Processor.
> 
> +  @retval EFI_INVALID_PARAMTER  This or Buffer is NULL.
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +EFIAPI
> 
> +SmramSaveStateReadRegisterByIndex (
> 
> +  IN UINTN  CpuIndex,
> 
> +  IN UINTN  RegisterIndex,
> 
> +  IN UINTN  Width,
> 
> +  OUT VOID  *Buffer
> 
> +  );
> 
> +
> 
> +#endif
> 
> diff --git
> a/UefiCpuPkg/Library/SmmSmramSaveStateLib/Amd/SmramSaveState.c
> b/UefiCpuPkg/Library/SmmSmramSaveStateLib/Amd/SmramSaveState.c
> new file mode 100644
> index 000000000000..af2eeedc71f5
> --- /dev/null
> +++
> b/UefiCpuPkg/Library/SmmSmramSaveStateLib/Amd/SmramSaveState.c
> @@ -0,0 +1,318 @@
> +/** @file
> 
> +Provides services to access SMRAM Save State Map
> 
> +
> 
> +Copyright (c) 2010 - 2019, Intel Corporation. All rights reserved.<BR>
> 
> +Copyright (C) 2023 Advanced Micro Devices, Inc. All rights
> +reserved.<BR>
> 
> +SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> +
> 
> +**/
> 
> +
> 
> +#include "SmramSaveState.h"
> 
> +#include <Register/Amd/SmramSaveStateMap.h>
> 
> +#include <Library/BaseLib.h>
> 
> +
> 
> +#define EFER_ADDRESS                            0XC0000080ul
> 
> +#define SMM_SAVE_STATE_REGISTER_SMMREVID_INDEX  1
> 
> +
> 
> +// Macro used to simplify the lookup table entries of type
> +CPU_SMM_SAVE_STATE_LOOKUP_ENTRY
> 
> +#define SMM_CPU_OFFSET(Field)  OFFSET_OF
> (AMD_SMRAM_SAVE_STATE_MAP,
> +Field)
> 
> +
> 
> +// Table used by SmramSaveStateGetRegisterIndex() to convert an
> +EFI_SMM_SAVE_STATE_REGISTER
> 
> +// value to an index into a table of type
> +CPU_SMM_SAVE_STATE_LOOKUP_ENTRY
> 
> +CONST CPU_SMM_SAVE_STATE_REGISTER_RANGE
> mSmmSmramCpuRegisterRanges[] =
> +{
> 
> +  SMM_REGISTER_RANGE (EFI_SMM_SAVE_STATE_REGISTER_GDTBASE,
> + EFI_SMM_SAVE_STATE_REGISTER_LDTINFO),
> 
> +  SMM_REGISTER_RANGE (EFI_SMM_SAVE_STATE_REGISTER_ES,
> EFI_SMM_SAVE_STATE_REGISTER_RIP),
> 
> +  SMM_REGISTER_RANGE (EFI_SMM_SAVE_STATE_REGISTER_RFLAGS,
> + EFI_SMM_SAVE_STATE_REGISTER_CR4),
> 
> +  { (EFI_SMM_SAVE_STATE_REGISTER)0,
> (EFI_SMM_SAVE_STATE_REGISTER)0,      0}
> 
> +};
> 
> +
> 
> +// Lookup table used to retrieve the widths and offsets associated with
> +each
> 
> +// supported EFI_SMM_SAVE_STATE_REGISTER value
> 
> +CONST CPU_SMM_SAVE_STATE_LOOKUP_ENTRY
> mSmmSmramCpuWidthOffset[] = {
> 
> +  { 0, 0, 0,                             0,                                     FALSE },                                          //
> Reserved
> 
> +
> 
> +  //
> 
> +  // Internally defined CPU Save State Registers. Not defined in PI SMM CPU
> Protocol.
> 
> +  //
> 
> +  { 4, 4, SMM_CPU_OFFSET (x86.SMMRevId), SMM_CPU_OFFSET
> (x64.SMMRevId),         0, FALSE},                                        //
> SMM_SAVE_STATE_REGISTER_SMMREVID_INDEX  = 1
> 
> +
> 
> +  //
> 
> +  // CPU Save State registers defined in PI SMM CPU Protocol.
> 
> +  //
> 
> +  { 4, 8, SMM_CPU_OFFSET (x86.GDTBase),  SMM_CPU_OFFSET
> (x64._GDTRBaseLoDword), SMM_CPU_OFFSET (x64._GDTRBaseHiDword),
> FALSE},    //  EFI_SMM_SAVE_STATE_REGISTER_GDTBASE  = 4
> 
> +  { 0, 8, 0,                             SMM_CPU_OFFSET (x64._IDTRBaseLoDword),
> SMM_CPU_OFFSET (x64._IDTRBaseLoDword), FALSE},    //
> EFI_SMM_SAVE_STATE_REGISTER_IDTBASE  = 5
> 
> +  { 0, 8, 0,                             SMM_CPU_OFFSET (x64._LDTRBaseLoDword),
> SMM_CPU_OFFSET (x64._LDTRBaseLoDword), FALSE},    //
> EFI_SMM_SAVE_STATE_REGISTER_LDTBASE  = 6
> 
> +  { 0, 2, 0,                             SMM_CPU_OFFSET (x64._GDTRLimit),       0, FALSE},
> //  EFI_SMM_SAVE_STATE_REGISTER_GDTLIMIT = 7
> 
> +  { 0, 2, 0,                             SMM_CPU_OFFSET (x64._IDTRLimit),       0, FALSE},
> //  EFI_SMM_SAVE_STATE_REGISTER_IDTLIMIT = 8
> 
> +  { 0, 4, 0,                             SMM_CPU_OFFSET (x64._LDTRLimit),       0, FALSE},
> //  EFI_SMM_SAVE_STATE_REGISTER_LDTLIMIT = 9
> 
> +  { 0, 0, 0,                             0,                                     0, FALSE},                                        //
> EFI_SMM_SAVE_STATE_REGISTER_LDTINFO  = 10
> 
> +  { 4, 2, SMM_CPU_OFFSET (x86._ES),      SMM_CPU_OFFSET (x64._ES),
> 0, FALSE},                                        //  EFI_SMM_SAVE_STATE_REGISTER_ES       =
> 20
> 
> +  { 4, 2, SMM_CPU_OFFSET (x86._CS),      SMM_CPU_OFFSET (x64._CS),
> 0, FALSE},                                        //  EFI_SMM_SAVE_STATE_REGISTER_CS       =
> 21
> 
> +  { 4, 2, SMM_CPU_OFFSET (x86._SS),      SMM_CPU_OFFSET (x64._SS),
> 0, FALSE},                                        //  EFI_SMM_SAVE_STATE_REGISTER_SS       =
> 22
> 
> +  { 4, 2, SMM_CPU_OFFSET (x86._DS),      SMM_CPU_OFFSET (x64._DS),
> 0, FALSE},                                        //  EFI_SMM_SAVE_STATE_REGISTER_DS       =
> 23
> 
> +  { 4, 2, SMM_CPU_OFFSET (x86._FS),      SMM_CPU_OFFSET (x64._FS),
> 0, FALSE},                                        //  EFI_SMM_SAVE_STATE_REGISTER_FS       =
> 24
> 
> +  { 4, 2, SMM_CPU_OFFSET (x86._GS),      SMM_CPU_OFFSET (x64._GS),
> 0, FALSE},                                        //  EFI_SMM_SAVE_STATE_REGISTER_GS       =
> 25
> 
> +  { 0, 2, 0,                             SMM_CPU_OFFSET (x64._LDTR),            0, FALSE},
> //  EFI_SMM_SAVE_STATE_REGISTER_LDTR_SEL = 26
> 
> +  { 0, 2, 0,                             SMM_CPU_OFFSET (x64._TR),              0, FALSE},
> //  EFI_SMM_SAVE_STATE_REGISTER_TR_SEL   = 27
> 
> +  { 4, 8, SMM_CPU_OFFSET (x86._DR7),     SMM_CPU_OFFSET (x64._DR7),
> SMM_CPU_OFFSET (x64._DR7)         + 4, FALSE},    //
> EFI_SMM_SAVE_STATE_REGISTER_DR7      = 28
> 
> +  { 4, 8, SMM_CPU_OFFSET (x86._DR6),     SMM_CPU_OFFSET (x64._DR6),
> SMM_CPU_OFFSET (x64._DR6)         + 4, FALSE},    //
> EFI_SMM_SAVE_STATE_REGISTER_DR6      = 29
> 
> +  { 0, 8, 0,                             SMM_CPU_OFFSET (x64._R8),
> SMM_CPU_OFFSET (x64._R8)          + 4, TRUE},     //
> EFI_SMM_SAVE_STATE_REGISTER_R8       = 30
> 
> +  { 0, 8, 0,                             SMM_CPU_OFFSET (x64._R9),
> SMM_CPU_OFFSET (x64._R9)          + 4, TRUE},     //
> EFI_SMM_SAVE_STATE_REGISTER_R9       = 31
> 
> +  { 0, 8, 0,                             SMM_CPU_OFFSET (x64._R10),
> SMM_CPU_OFFSET (x64._R10)         + 4, TRUE},     //
> EFI_SMM_SAVE_STATE_REGISTER_R10      = 32
> 
> +  { 0, 8, 0,                             SMM_CPU_OFFSET (x64._R11),
> SMM_CPU_OFFSET (x64._R11)         + 4, TRUE},     //
> EFI_SMM_SAVE_STATE_REGISTER_R11      = 33
> 
> +  { 0, 8, 0,                             SMM_CPU_OFFSET (x64._R12),
> SMM_CPU_OFFSET (x64._R12)         + 4, TRUE},     //
> EFI_SMM_SAVE_STATE_REGISTER_R12      = 34
> 
> +  { 0, 8, 0,                             SMM_CPU_OFFSET (x64._R13),
> SMM_CPU_OFFSET (x64._R13)         + 4, TRUE},     //
> EFI_SMM_SAVE_STATE_REGISTER_R13      = 35
> 
> +  { 0, 8, 0,                             SMM_CPU_OFFSET (x64._R14),
> SMM_CPU_OFFSET (x64._R14)         + 4, TRUE},     //
> EFI_SMM_SAVE_STATE_REGISTER_R14      = 36
> 
> +  { 0, 8, 0,                             SMM_CPU_OFFSET (x64._R15),
> SMM_CPU_OFFSET (x64._R15)         + 4, TRUE},     //
> EFI_SMM_SAVE_STATE_REGISTER_R15      = 37
> 
> +  { 4, 8, SMM_CPU_OFFSET (x86._EAX),     SMM_CPU_OFFSET (x64._RAX),
> SMM_CPU_OFFSET (x64._RAX)         + 4, TRUE},     //
> EFI_SMM_SAVE_STATE_REGISTER_RAX      = 38
> 
> +  { 4, 8, SMM_CPU_OFFSET (x86._EBX),     SMM_CPU_OFFSET (x64._RBX),
> SMM_CPU_OFFSET (x64._RBX)         + 4, TRUE},     //
> EFI_SMM_SAVE_STATE_REGISTER_RBX      = 39
> 
> +  { 4, 8, SMM_CPU_OFFSET (x86._ECX),     SMM_CPU_OFFSET (x64._RCX),
> SMM_CPU_OFFSET (x64._RCX)         + 4, TRUE},     //
> EFI_SMM_SAVE_STATE_REGISTER_RBX      = 39
> 
> +  { 4, 8, SMM_CPU_OFFSET (x86._EDX),     SMM_CPU_OFFSET (x64._RDX),
> SMM_CPU_OFFSET (x64._RDX)         + 4, TRUE},     //
> EFI_SMM_SAVE_STATE_REGISTER_RDX      = 41
> 
> +  { 4, 8, SMM_CPU_OFFSET (x86._ESP),     SMM_CPU_OFFSET (x64._RSP),
> SMM_CPU_OFFSET (x64._RSP)         + 4, TRUE},     //
> EFI_SMM_SAVE_STATE_REGISTER_RSP      = 42
> 
> +  { 4, 8, SMM_CPU_OFFSET (x86._EBP),     SMM_CPU_OFFSET (x64._RBP),
> SMM_CPU_OFFSET (x64._RBP)         + 4, TRUE},     //
> EFI_SMM_SAVE_STATE_REGISTER_RBP      = 43
> 
> +  { 4, 8, SMM_CPU_OFFSET (x86._ESI),     SMM_CPU_OFFSET (x64._RSI),
> SMM_CPU_OFFSET (x64._RSI)         + 4, TRUE},     //
> EFI_SMM_SAVE_STATE_REGISTER_RSI      = 44
> 
> +  { 4, 8, SMM_CPU_OFFSET (x86._EDI),     SMM_CPU_OFFSET (x64._RDI),
> SMM_CPU_OFFSET (x64._RDI)         + 4, TRUE},     //
> EFI_SMM_SAVE_STATE_REGISTER_RDI      = 45
> 
> +  { 4, 8, SMM_CPU_OFFSET (x86._EIP),     SMM_CPU_OFFSET (x64._RIP),
> SMM_CPU_OFFSET (x64._RIP)         + 4, TRUE},     //
> EFI_SMM_SAVE_STATE_REGISTER_RIP      = 46
> 
> +
> 
> +  { 4, 8, SMM_CPU_OFFSET (x86._EFLAGS),  SMM_CPU_OFFSET
> (x64._RFLAGS),          SMM_CPU_OFFSET (x64._RFLAGS)      + 4, TRUE},     //
> EFI_SMM_SAVE_STATE_REGISTER_RFLAGS   = 51
> 
> +  { 4, 8, SMM_CPU_OFFSET (x86._CR0),     SMM_CPU_OFFSET (x64._CR0),
> SMM_CPU_OFFSET (x64._CR0)         + 4, FALSE},    //
> EFI_SMM_SAVE_STATE_REGISTER_CR0      = 52
> 
> +  { 4, 8, SMM_CPU_OFFSET (x86._CR3),     SMM_CPU_OFFSET (x64._CR3),
> SMM_CPU_OFFSET (x64._CR3)         + 4, FALSE},    //
> EFI_SMM_SAVE_STATE_REGISTER_CR3      = 53
> 
> +  { 0, 8, 0,                             SMM_CPU_OFFSET (x64._CR4),
> SMM_CPU_OFFSET (x64._CR4)         + 4, FALSE},    //
> EFI_SMM_SAVE_STATE_REGISTER_CR4      = 54
> 
> +  { 0, 0, 0,                             0,                                     0     }
> 
> +};
> 
> +
> 
> +/**
> 
> +  Read an SMM Save State register on the target processor.  If this
> + function
> 
> +  returns EFI_UNSUPPORTED, then the caller is responsible for reading
> + the
> 
> +  SMM Save Sate register.
> 
> +
> 
> +  @param[in]  CpuIndex  The index of the CPU to read the SMM Save
> + State.  The
> 
> +                        value must be between 0 and the NumberOfCpus
> + field in
> 
> +                        the System Management System Table (SMST).
> 
> +  @param[in]  Register  The SMM Save State register to read.
> 
> +  @param[in]  Width     The number of bytes to read from the CPU save
> state.
> 
> +  @param[out] Buffer    Upon return, this holds the CPU register value read
> 
> +                        from the save state.
> 
> +
> 
> +  @retval EFI_SUCCESS           The register was read from Save State.
> 
> +  @retval EFI_INVALID_PARAMTER  Buffer is NULL.
> 
> +  @retval EFI_UNSUPPORTED       This function does not support reading
EFI_NOT_FOUND is missed.

> Register.
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +EFIAPI
> 
> +SmramSaveStateReadRegister (
> 
> +  IN  UINTN                        CpuIndex,
> 
> +  IN  EFI_SMM_SAVE_STATE_REGISTER  Register,
> 
> +  IN  UINTN                        Width,
> 
> +  OUT VOID                         *Buffer
> 
> +  )
> 
> +{
> 
> +  UINT32                      SmmRevId;
> 
> +  EFI_SMM_SAVE_STATE_IO_INFO  *IoInfo;
> 
> +  AMD_SMRAM_SAVE_STATE_MAP    *CpuSaveState;
> 
> +  UINT8                       DataWidth;
> 
> +
> 
> +  // Read CPU State
> 
> +  CpuSaveState = (AMD_SMRAM_SAVE_STATE_MAP
> + *)gSmst->CpuSaveState[CpuIndex];
> 
> +
> 
> +  // Check for special EFI_SMM_SAVE_STATE_REGISTER_LMA
> 
> +  if (Register == EFI_SMM_SAVE_STATE_REGISTER_LMA) {
> 
> +    // Only byte access is supported for this register
> 
> +    if (Width != 1) {
> 
> +      return EFI_INVALID_PARAMETER;
> 
> +    }
> 
> +
> 
> +    *(UINT8 *)Buffer = SmramSaveStateGetRegisterLma ();
> 
> +
> 
> +    return EFI_SUCCESS;
> 
> +  }
> 
> +
> 
> +  // Check for special EFI_SMM_SAVE_STATE_REGISTER_IO
> 
> +
> 
> +  if (Register == EFI_SMM_SAVE_STATE_REGISTER_IO) {
> 
> +    //
> 
> +    // Get SMM Revision ID
> 
> +    //
> 
> +    SmramSaveStateReadRegisterByIndex (CpuIndex,
> + SMM_SAVE_STATE_REGISTER_SMMREVID_INDEX, sizeof (SmmRevId),
> &SmmRevId);
> 
> +
> 
> +    //
> 
> +    // See if the CPU supports the IOMisc register in the save state
> 
> +    //
> 
> +    if (SmmRevId < AMD_SMM_MIN_REV_ID_X64) {
> 
> +      return EFI_NOT_FOUND;
> 
> +    }
> 
> +
> 
> +    // Check if IO Restart Dword [IO Trap] is valid or not using bit 1.
> 
> +    if (!(CpuSaveState->x64.IO_DWord & 0x02u)) {
> 
> +      return EFI_NOT_FOUND;
> 
> +    }
> 
> +
> 
> +    // Zero the IoInfo structure that will be returned in Buffer
> 
> +    IoInfo = (EFI_SMM_SAVE_STATE_IO_INFO *)Buffer;
> 
> +    ZeroMem (IoInfo, sizeof (EFI_SMM_SAVE_STATE_IO_INFO));
> 
> +
> 
> +    IoInfo->IoPort = (UINT16)(CpuSaveState->x64.IO_DWord >> 16u);
> 
> +
> 
> +    if (CpuSaveState->x64.IO_DWord & 0x10u) {
> 
> +      IoInfo->IoWidth = EFI_SMM_SAVE_STATE_IO_WIDTH_UINT8;
> 
> +      DataWidth       = 0x01u;
> 
> +    } else if (CpuSaveState->x64.IO_DWord & 0x20u) {
> 
> +      IoInfo->IoWidth = EFI_SMM_SAVE_STATE_IO_WIDTH_UINT16;
> 
> +      DataWidth       = 0x02u;
> 
> +    } else {
> 
> +      IoInfo->IoWidth = EFI_SMM_SAVE_STATE_IO_WIDTH_UINT32;
> 
> +      DataWidth       = 0x04u;
> 
> +    }
> 
> +
> 
> +    if (CpuSaveState->x64.IO_DWord & 0x01u) {
> 
> +      IoInfo->IoType = EFI_SMM_SAVE_STATE_IO_TYPE_INPUT;
> 
> +    } else {
> 
> +      IoInfo->IoType = EFI_SMM_SAVE_STATE_IO_TYPE_OUTPUT;
> 
> +    }
> 
> +
> 
> +    if ((IoInfo->IoType == EFI_SMM_SAVE_STATE_IO_TYPE_INPUT) ||
> + (IoInfo->IoType == EFI_SMM_SAVE_STATE_IO_TYPE_OUTPUT)) {
> 
> +      SmramSaveStateReadRegister (CpuIndex,
> + EFI_SMM_SAVE_STATE_REGISTER_RAX, DataWidth, &IoInfo->IoData);
> 
> +    }
> 
> +
> 
> +    return EFI_SUCCESS;
> 
> +  }
> 
> +
> 
> +  // Convert Register to a register lookup table index
> 
> +  return SmramSaveStateReadRegisterByIndex (CpuIndex,
> + SmramSaveStateGetRegisterIndex (Register), Width, Buffer);
> 
> +}
> 
> +
> 
> +/**
> 
> +  Writes an SMM Save State register on the target processor.  If this
> + function
> 
> +  returns EFI_UNSUPPORTED, then the caller is responsible for writing
> + the
> 
> +  SMM Save Sate register.
> 
> +
> 
> +  @param[in] CpuIndex  The index of the CPU to write the SMM Save
> + State.  The
> 
> +                       value must be between 0 and the NumberOfCpus
> + field in
> 
> +                       the System Management System Table (SMST).
> 
> +  @param[in] Register  The SMM Save State register to write.
> 
> +  @param[in] Width     The number of bytes to write to the CPU save state.
> 
> +  @param[in] Buffer    Upon entry, this holds the new CPU register value.
> 
> +
> 
> +  @retval EFI_SUCCESS           The register was written to Save State.
> 
> +  @retval EFI_INVALID_PARAMTER  Buffer is NULL.
> 
> +  @retval EFI_UNSUPPORTED       This function does not support writing

EFI_NOT_FOUND is missed.

Thanks
Abner

> Register.
> 
> +**/
> 
> +EFI_STATUS
> 
> +EFIAPI
> 
> +SmramSaveStateWriteRegister (
> 
> +  IN UINTN                        CpuIndex,
> 
> +  IN EFI_SMM_SAVE_STATE_REGISTER  Register,
> 
> +  IN UINTN                        Width,
> 
> +  IN CONST VOID                   *Buffer
> 
> +  )
> 
> +{
> 
> +  UINTN                     RegisterIndex;
> 
> +  AMD_SMRAM_SAVE_STATE_MAP  *CpuSaveState;
> 
> +
> 
> +  //
> 
> +  // Writes to EFI_SMM_SAVE_STATE_REGISTER_LMA are ignored
> 
> +  //
> 
> +  if (Register == EFI_SMM_SAVE_STATE_REGISTER_LMA) {
> 
> +    return EFI_SUCCESS;
> 
> +  }
> 
> +
> 
> +  //
> 
> +  // Writes to EFI_SMM_SAVE_STATE_REGISTER_IO are not supported
> 
> +  //
> 
> +  if (Register == EFI_SMM_SAVE_STATE_REGISTER_IO) {
> 
> +    return EFI_NOT_FOUND;
> 
> +  }
> 
> +
> 
> +  //
> 
> +  // Convert Register to a register lookup table index
> 
> +  //
> 
> +  RegisterIndex = SmramSaveStateGetRegisterIndex (Register);
> 
> +  if (RegisterIndex == 0) {
> 
> +    return EFI_NOT_FOUND;
> 
> +  }
> 
> +
> 
> +  CpuSaveState = gSmst->CpuSaveState[CpuIndex];
> 
> +
> 
> +  //
> 
> +  // Do not write non-writable SaveState, because it will cause exception.
> 
> +  //
> 
> +  if (!mSmmSmramCpuWidthOffset[RegisterIndex].Writeable) {
> 
> +    return EFI_UNSUPPORTED;
> 
> +  }
> 
> +
> 
> +  //
> 
> +  // Check CPU mode
> 
> +  //
> 
> +  if (SmramSaveStateGetRegisterLma () ==
> + EFI_SMM_SAVE_STATE_REGISTER_LMA_32BIT) {
> 
> +    //
> 
> +    // If 32-bit mode width is zero, then the specified register can
> + not be accessed
> 
> +    //
> 
> +    if (mSmmSmramCpuWidthOffset[RegisterIndex].Width32 == 0) {
> 
> +      return EFI_NOT_FOUND;
> 
> +    }
> 
> +
> 
> +    //
> 
> +    // If Width is bigger than the 32-bit mode width, then the
> + specified register can not be accessed
> 
> +    //
> 
> +    if (Width > mSmmSmramCpuWidthOffset[RegisterIndex].Width32) {
> 
> +      return EFI_INVALID_PARAMETER;
> 
> +    }
> 
> +
> 
> +    //
> 
> +    // Write SMM State register
> 
> +    //
> 
> +    ASSERT (CpuSaveState != NULL);
> 
> +    CopyMem ((UINT8 *)CpuSaveState +
> + mSmmSmramCpuWidthOffset[RegisterIndex].Offset32, Buffer, Width);
> 
> +  } else {
> 
> +    //
> 
> +    // If 64-bit mode width is zero, then the specified register can
> + not be accessed
> 
> +    //
> 
> +    if (mSmmSmramCpuWidthOffset[RegisterIndex].Width64 == 0) {
> 
> +      return EFI_NOT_FOUND;
> 
> +    }
> 
> +
> 
> +    //
> 
> +    // If Width is bigger than the 64-bit mode width, then the
> + specified register can not be accessed
> 
> +    //
> 
> +    if (Width > mSmmSmramCpuWidthOffset[RegisterIndex].Width64) {
> 
> +      return EFI_INVALID_PARAMETER;
> 
> +    }
> 
> +
> 
> +    //
> 
> +    // Write lower 32-bits of SMM State register
> 
> +    //
> 
> +    CopyMem ((UINT8 *)CpuSaveState +
> + mSmmSmramCpuWidthOffset[RegisterIndex].Offset64Lo, Buffer, MIN (4,
> + Width));
> 
> +    if (Width >= 4) {
> 
> +      //
> 
> +      // Write upper 32-bits of SMM State register
> 
> +      //
> 
> +      CopyMem ((UINT8 *)CpuSaveState +
> + mSmmSmramCpuWidthOffset[RegisterIndex].Offset64Hi, (UINT8 *)Buffer
> +
> + 4, Width - 4);
> 
> +    }
> 
> +  }
> 
> +
> 
> +  return EFI_SUCCESS;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Returns LMA value of the Processor.
> 
> +
> 
> +  @param[in]  VOID
> 
> +
> 
> +  @retval     UINT8 returns LMA bit value.
> 
> +**/
> 
> +UINT8
> 
> +EFIAPI
> 
> +SmramSaveStateGetRegisterLma (
> 
> +  VOID
> 
> +  )
> 
> +{
> 
> +  UINT32  LMAValue;
> 
> +
> 
> +  LMAValue = (UINT32)AsmReadMsr64 (EFER_ADDRESS) & LMA;
> 
> +  if (LMAValue) {
> 
> +    return EFI_SMM_SAVE_STATE_REGISTER_LMA_64BIT;
> 
> +  }
> 
> +
> 
> +  return EFI_SMM_SAVE_STATE_REGISTER_LMA_32BIT;
> 
> +}
> 
> diff --git
> a/UefiCpuPkg/Library/SmmSmramSaveStateLib/SmramSaveStateCommon.c
> b/UefiCpuPkg/Library/SmmSmramSaveStateLib/SmramSaveStateCommon.c
> new file mode 100644
> index 000000000000..98e89f9eec3f
> --- /dev/null
> +++
> b/UefiCpuPkg/Library/SmmSmramSaveStateLib/SmramSaveStateCommon.c
> @@ -0,0 +1,124 @@
> +/** @file
> 
> +  Provides common supporting function to access SMRAM Save State Map
> 
> +
> 
> +  Copyright (c) 2010 - 2019, Intel Corporation. All rights
> + reserved.<BR>
> 
> +  Copyright (C) 2023 Advanced Micro Devices, Inc. All rights
> + reserved.<BR>
> 
> +
> 
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> +
> 
> +**/
> 
> +
> 
> +#include "SmramSaveState.h"
> 
> +
> 
> +extern CONST CPU_SMM_SAVE_STATE_REGISTER_RANGE
> +mSmmSmramCpuRegisterRanges[];
> 
> +extern CONST CPU_SMM_SAVE_STATE_LOOKUP_ENTRY
> mSmmSmramCpuWidthOffset[];
> 
> +
> 
> +/**
> 
> +  Read information from the CPU save state.
> 
> +
> 
> +  @param  Register  Specifies the CPU register to read form the save state.
> 
> +
> 
> +  @retval 0   Register is not valid
> 
> +  @retval >0  Index into mSmmSmramCpuWidthOffset[] associated with
> + Register
> 
> +
> 
> +**/
> 
> +UINTN
> 
> +EFIAPI
> 
> +SmramSaveStateGetRegisterIndex (
> 
> +  IN EFI_SMM_SAVE_STATE_REGISTER  Register
> 
> +  )
> 
> +{
> 
> +  UINTN  Index;
> 
> +  UINTN  Offset;
> 
> +
> 
> +  for (Index = 0, Offset = SMM_SAVE_STATE_REGISTER_MAX_INDEX;
> + mSmmSmramCpuRegisterRanges[Index].Length != 0; Index++) {
> 
> +    if ((Register >= mSmmSmramCpuRegisterRanges[Index].Start) &&
> + (Register <= mSmmSmramCpuRegisterRanges[Index].End)) {
> 
> +      return Register - mSmmSmramCpuRegisterRanges[Index].Start +
> + Offset;
> 
> +    }
> 
> +
> 
> +    Offset += mSmmSmramCpuRegisterRanges[Index].Length;
> 
> +  }
> 
> +
> 
> +  return 0;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Read a CPU Save State register on the target processor.
> 
> +
> 
> +  This function abstracts the differences that whether the CPU Save
> + State register is in the
> 
> +  IA32 CPU Save State Map or X64 CPU Save State Map.
> 
> +
> 
> +  This function supports reading a CPU Save State register in SMBase
> relocation handler.
> 
> +
> 
> +  @param[in]  CpuIndex       Specifies the zero-based index of the CPU save
> state.
> 
> +  @param[in]  RegisterIndex  Index into mSmmSmramCpuWidthOffset[]
> look up table.
> 
> +  @param[in]  Width          The number of bytes to read from the CPU save
> state.
> 
> +  @param[out] Buffer         Upon return, this holds the CPU register value
> read from the save state.
> 
> +
> 
> +  @retval EFI_SUCCESS           The register was read from Save State.
> 
> +  @retval EFI_NOT_FOUND         The register is not defined for the Save
> State of Processor.
> 
> +  @retval EFI_INVALID_PARAMTER  This or Buffer is NULL.
> 
> +
> 
> +**/
> 
> +EFI_STATUS
> 
> +EFIAPI
> 
> +SmramSaveStateReadRegisterByIndex (
> 
> +  IN UINTN  CpuIndex,
> 
> +  IN UINTN  RegisterIndex,
> 
> +  IN UINTN  Width,
> 
> +  OUT VOID  *Buffer
> 
> +  )
> 
> +{
> 
> +  if (RegisterIndex == 0) {
> 
> +    return EFI_NOT_FOUND;
> 
> +  }
> 
> +
> 
> +  if (SmramSaveStateGetRegisterLma () ==
> + EFI_SMM_SAVE_STATE_REGISTER_LMA_32BIT) {
> 
> +    //
> 
> +    // If 32-bit mode width is zero, then the specified register can
> + not be accessed
> 
> +    //
> 
> +    if (mSmmSmramCpuWidthOffset[RegisterIndex].Width32 == 0) {
> 
> +      return EFI_NOT_FOUND;
> 
> +    }
> 
> +
> 
> +    //
> 
> +    // If Width is bigger than the 32-bit mode width, then the
> + specified register can not be accessed
> 
> +    //
> 
> +    if (Width > mSmmSmramCpuWidthOffset[RegisterIndex].Width32) {
> 
> +      return EFI_INVALID_PARAMETER;
> 
> +    }
> 
> +
> 
> +    //
> 
> +    // Write return buffer
> 
> +    //
> 
> +    ASSERT (gSmst->CpuSaveState[CpuIndex] != NULL);
> 
> +    CopyMem (Buffer, (UINT8 *)gSmst->CpuSaveState[CpuIndex] +
> + mSmmSmramCpuWidthOffset[RegisterIndex].Offset32, Width);
> 
> +  } else {
> 
> +    //
> 
> +    // If 64-bit mode width is zero, then the specified register can
> + not be accessed
> 
> +    //
> 
> +    if (mSmmSmramCpuWidthOffset[RegisterIndex].Width64 == 0) {
> 
> +      return EFI_NOT_FOUND;
> 
> +    }
> 
> +
> 
> +    //
> 
> +    // If Width is bigger than the 64-bit mode width, then the
> + specified register can not be accessed
> 
> +    //
> 
> +    if (Width > mSmmSmramCpuWidthOffset[RegisterIndex].Width64) {
> 
> +      return EFI_INVALID_PARAMETER;
> 
> +    }
> 
> +
> 
> +    //
> 
> +    // Write lower 32-bits of return buffer
> 
> +    //
> 
> +    CopyMem (Buffer, (UINT8 *)gSmst->CpuSaveState[CpuIndex] +
> + mSmmSmramCpuWidthOffset[RegisterIndex].Offset64Lo, MIN (4, Width));
> 
> +    if (Width >= 4) {
> 
> +      //
> 
> +      // Write upper 32-bits of return buffer
> 
> +      //
> 
> +      CopyMem ((UINT8 *)Buffer + 4, (UINT8
> + *)gSmst->CpuSaveState[CpuIndex] +
> + mSmmSmramCpuWidthOffset[RegisterIndex].Offset64Hi, Width - 4);
> 
> +    }
> 
> +  }
> 
> +
> 
> +  return EFI_SUCCESS;
> 
> +}
> 
> --
> 2.25.1
> 
> 
> 
> 
> 


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#98519): https://edk2.groups.io/g/devel/message/98519
Mute This Topic: https://groups.io/mt/96195138/1813853
Group Owner: devel+owner at edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [edk2-devel-archive at redhat.com]
-=-=-=-=-=-=-=-=-=-=-=-




More information about the edk2-devel-archive mailing list