From mboxrd@z Thu Jan 1 00:00:00 1970 Subject: Re: [edk2-devel] [PATCH v1 4/5] UefiCpuPkg: Implements SmmCpuFeaturesLib for AMD Family To: Abdul Lateef Attar ,devel@edk2.groups.io From: "Chang, Abner" X-Originating-Location: TW (185.221.70.44) X-Originating-Platform: Windows Chrome 107 User-Agent: GROUPS.IO Web Poster MIME-Version: 1.0 Date: Wed, 07 Dec 2022 21:07:32 -0800 References: <79f976894da303d126fca5f6ace608391082d288.1670332633.git.abdattar@amd.com> In-Reply-To: <79f976894da303d126fca5f6ace608391082d288.1670332633.git.abdattar@amd.com> Message-ID: <24898.1670476052499217148@groups.io> Content-Type: multipart/alternative; boundary="deqQsT29TNeltRygQVqk" --deqQsT29TNeltRygQVqk Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Hi Abdul, This is a little bit confusing because there is one SmramSaveStae.c under P= ismmCpuDxeSmm however another one is under SmmCpuFeaturesLib for AMD. I would suggest we introduce SmramSaveState library under UefiCpuPkg/Librar= y which is used by both PismmCpuDxeSmm=C2=A0and SmmCpuFeaturesLib. This mak= es the library reference clear without duplication. We can have AMD SmramSaveStateLib instance and just name it as SmramSaveSta= teLib.c. That is Intel's decision if they want to move their implementation= from PismmCpuDxeSmm=C2=A0to SmramSaveState or not. Thanks Abner On Tue, Dec 6, 2022 at 09:23 PM, Abdul Lateef Attar wrote: >=20 > From: Abdul Lateef Attar >=20 > BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3D4182 >=20 > Implements interfaces to read and write save state > registers of AMD's processor family. > Initializes processor SMMADDR and MASK depends > on PcdSmrrEnable flag. > Program or corrects the IP once control returns from SMM. >=20 > Cc: Paul Grimes > Cc: Garrett Kirkendall > Cc: Abner Chang > Cc: Eric Dong > Cc: Ray Ni > Cc: Rahul Kumar > Signed-off-by: Abdul Lateef Attar > --- > .../AmdSmmCpuFeaturesLib.inf | 2 + > .../SmmCpuFeaturesLib/Amd/SmramSaveState.h | 109 +++++ > .../SmmCpuFeaturesLib/Amd/SmmCpuFeaturesLib.c | 97 ++++- > .../SmmCpuFeaturesLib/Amd/SmramSaveState.c | 409 ++++++++++++++++++ > 4 files changed, 612 insertions(+), 5 deletions(-) > create mode 100644 > UefiCpuPkg/Library/SmmCpuFeaturesLib/Amd/SmramSaveState.h > create mode 100644 > UefiCpuPkg/Library/SmmCpuFeaturesLib/Amd/SmramSaveState.c >=20 > diff --git a/UefiCpuPkg/Library/SmmCpuFeaturesLib/AmdSmmCpuFeaturesLib.in= f > b/UefiCpuPkg/Library/SmmCpuFeaturesLib/AmdSmmCpuFeaturesLib.inf > index 08ac0262022f..95eb31d16ead 100644 > --- a/UefiCpuPkg/Library/SmmCpuFeaturesLib/AmdSmmCpuFeaturesLib.inf > +++ b/UefiCpuPkg/Library/SmmCpuFeaturesLib/AmdSmmCpuFeaturesLib.inf > @@ -21,6 +21,8 @@ [Sources] > SmmCpuFeaturesLib.c > SmmCpuFeaturesLibCommon.c > Amd/SmmCpuFeaturesLib.c > + Amd/SmramSaveState.c > + Amd/SmramSaveState.h >=20 > [Packages] > MdePkg/MdePkg.dec > diff --git a/UefiCpuPkg/Library/SmmCpuFeaturesLib/Amd/SmramSaveState.h > b/UefiCpuPkg/Library/SmmCpuFeaturesLib/Amd/SmramSaveState.h > new file mode 100644 > index 000000000000..290ebdbc9227 > --- /dev/null > +++ b/UefiCpuPkg/Library/SmmCpuFeaturesLib/Amd/SmramSaveState.h > @@ -0,0 +1,109 @@ > +/** @file > +SMRAM Save State Map header file. > + > +Copyright (c) 2010 - 2019, Intel Corporation. All rights reserved.
> +Copyright (C) 2022 Advanced Micro Devices, Inc. All rights reserved.
> +SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#ifndef SMRAM_SAVESTATE_H_ > +#define SMRAM_SAVESTATE_H_ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +// EFER register LMA bit > +#define LMA BIT10 > + > +// Machine Specific Registers (MSRs) > +#define SMMADDR_ADDRESS 0xC0010112ul > +#define SMMMASK_ADDRESS 0xC0010113ul > +#define EFER_ADDRESS 0XC0000080ul > + > +// 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= ) >=20 > + > +// 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 } > + > +// 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 > + > +#define SMM_SAVE_STATE_REGISTER_SMMREVID_INDEX 1 > +#define SMM_SAVE_STATE_REGISTER_MAX_INDEX 2 > + > +typedef struct { > + UINT8 Width32; > + UINT8 Width64; > + UINT16 Offset32; > + UINT16 Offset64Lo; > + UINT16 Offset64Hi; > + BOOLEAN Writeable; > +} CPU_SMM_SAVE_STATE_LOOKUP_ENTRY; > + > +/** > + 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. Th= e >=20 > + 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 Register= . >=20 > + > +**/ > +EFI_STATUS > +EFIAPI > +InternalSmmCpuFeaturesReadSaveStateRegister ( > + IN UINTN CpuIndex, > + IN EFI_SMM_SAVE_STATE_REGISTER Register, > + IN UINTN Width, > + OUT VOID *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 Register= . >=20 > +**/ > +EFI_STATUS > +EFIAPI > +InternalSmmCpuFeaturesWriteSaveStateRegister ( > + IN UINTN CpuIndex, > + IN EFI_SMM_SAVE_STATE_REGISTER Register, > + IN UINTN Width, > + IN CONST VOID *Buffer > + ); > + > +#endif > diff --git a/UefiCpuPkg/Library/SmmCpuFeaturesLib/Amd/SmmCpuFeaturesLib.c > b/UefiCpuPkg/Library/SmmCpuFeaturesLib/Amd/SmmCpuFeaturesLib.c > index dc3fed0302d2..10bed4116397 100644 > --- a/UefiCpuPkg/Library/SmmCpuFeaturesLib/Amd/SmmCpuFeaturesLib.c > +++ b/UefiCpuPkg/Library/SmmCpuFeaturesLib/Amd/SmmCpuFeaturesLib.c > @@ -9,8 +9,10 @@ SPDX-License-Identifier: BSD-2-Clause-Patent >=20 > **/ >=20 > -#include > -#include > +#include "SmramSaveState.h" > + > +// The mode of the CPU at the time an SMI occurs > +extern UINT8 mSmmSaveStateRegisterLma; >=20 > /** > Read an SMM Save State register on the target processor. If this function > @@ -39,7 +41,7 @@ SmmCpuFeaturesReadSaveStateRegister ( > OUT VOID *Buffer > ) > { > - return EFI_SUCCESS; > + return InternalSmmCpuFeaturesReadSaveStateRegister (CpuIndex, Register, > Width, Buffer); > } >=20 > /** > @@ -67,7 +69,7 @@ SmmCpuFeaturesWriteSaveStateRegister ( > IN CONST VOID *Buffer > ) > { > - return EFI_SUCCESS; > + return InternalSmmCpuFeaturesWriteSaveStateRegister (CpuIndex, Register= , > Width, Buffer); > } >=20 > /** > @@ -82,6 +84,13 @@ CpuFeaturesLibInitialization ( > VOID > ) > { > + UINT32 LMAValue; > + > + LMAValue =3D (UINT32)AsmReadMsr64 (EFER_ADDRESS) & LMA; > + mSmmSaveStateRegisterLma =3D EFI_SMM_SAVE_STATE_REGISTER_LMA_32BIT; > + if (LMAValue) { > + mSmmSaveStateRegisterLma =3D EFI_SMM_SAVE_STATE_REGISTER_LMA_64BIT; > + } > } >=20 > /** > @@ -117,6 +126,52 @@ SmmCpuFeaturesInitializeProcessor ( > IN CPU_HOT_PLUG_DATA *CpuHotPlugData > ) > { > + AMD_SMRAM_SAVE_STATE_MAP *CpuState; > + UINT32 LMAValue; > + > + // > + // Configure SMBASE. > + // > + CpuState =3D (AMD_SMRAM_SAVE_STATE_MAP *)(UINTN)(SMM_DEFAULT_SMBASE + > SMRAM_SAVE_STATE_MAP_OFFSET); > + CpuState->x64.SMBASE =3D (UINT32)CpuHotPlugData->SmBase[CpuIndex]; > + > + // Re-initialize the value of mSmmSaveStateRegisterLma flag which might > have been changed in PiCpuSmmDxeSmm Driver > + // Entry point, to make sure correct value on AMD platform is assigned > to be used by SmmCpuFeaturesLib. > + LMAValue =3D (UINT32)AsmReadMsr64 (EFER_ADDRESS) & LMA; > + mSmmSaveStateRegisterLma =3D EFI_SMM_SAVE_STATE_REGISTER_LMA_32BIT; > + if (LMAValue) { > + mSmmSaveStateRegisterLma =3D EFI_SMM_SAVE_STATE_REGISTER_LMA_64BIT; > + } > + > + // > + // If SMRR is supported, then program SMRR base/mask MSRs. > + // The EFI_MSR_SMRR_PHYS_MASK_VALID bit is not set until the first > normal SMI. > + // The code that initializes SMM environment is running in normal mode > + // from SMRAM region. If SMRR is enabled here, then the SMRAM region > + // is protected and the normal mode code execution will fail. > + // > + if (FeaturePcdGet (PcdSmrrEnable)) { > + // > + // SMRR size cannot be less than 4-KBytes > + // SMRR size must be of length 2^n > + // SMRR base alignment cannot be less than SMRR length > + // > + if ((CpuHotPlugData->SmrrSize < SIZE_4KB) || > + (CpuHotPlugData->SmrrSize !=3D GetPowerOfTwo32 (CpuHotPlugData->SmrrSiz= e)) > || > + ((CpuHotPlugData->SmrrBase & ~(CpuHotPlugData->SmrrSize - 1)) !=3D > CpuHotPlugData->SmrrBase)) > + { > + // > + // Print message and halt if CPU is Monarch > + // > + if (IsMonarch) { > + DEBUG ((DEBUG_ERROR, "SMM Base/Size does not meet alignment/size > requirement!\n")); > + CpuDeadLoop (); > + } > + } else { > + AsmWriteMsr64 (SMMADDR_ADDRESS, CpuHotPlugData->SmrrBase); > + AsmWriteMsr64 (SMMMASK_ADDRESS, ((~(UINT64)(CpuHotPlugData->SmrrSize - > 1)) | 0x6600)); > + } > + } > } >=20 > /** > @@ -159,7 +214,39 @@ SmmCpuFeaturesHookReturnFromSmm ( > IN UINT64 NewInstructionPointer > ) > { > - return 0; > + UINT64 OriginalInstructionPointer; > + AMD_SMRAM_SAVE_STATE_MAP *AmdCpuState; > + > + AmdCpuState =3D (AMD_SMRAM_SAVE_STATE_MAP *)CpuState; > + > + if (mSmmSaveStateRegisterLma =3D=3D EFI_SMM_SAVE_STATE_REGISTER_LMA_32B= IT) { >=20 > + OriginalInstructionPointer =3D (UINT64)AmdCpuState->x86._EIP; > + AmdCpuState->x86._EIP =3D (UINT32)NewInstructionPointer; > + // > + // Clear the auto HALT restart flag so the RSM instruction returns > + // program control to the instruction following the HLT instruction. > + // > + if ((AmdCpuState->x86.AutoHALTRestart & BIT0) !=3D 0) { > + AmdCpuState->x86.AutoHALTRestart &=3D ~BIT0; > + } > + } else { > + OriginalInstructionPointer =3D AmdCpuState->x64._RIP; > + if ((AmdCpuState->x64.EFER & LMA) =3D=3D 0) { > + AmdCpuState->x64._RIP =3D (UINT32)NewInstructionPointer32; > + } else { > + AmdCpuState->x64._RIP =3D (UINT32)NewInstructionPointer; > + } > + > + // > + // Clear the auto HALT restart flag so the RSM instruction returns > + // program control to the instruction following the HLT instruction. > + // > + if ((AmdCpuState->x64.AutoHALTRestart & BIT0) !=3D 0) { > + AmdCpuState->x64.AutoHALTRestart &=3D ~BIT0; > + } > + } > + > + return OriginalInstructionPointer; > } >=20 > /** > diff --git a/UefiCpuPkg/Library/SmmCpuFeaturesLib/Amd/SmramSaveState.c > b/UefiCpuPkg/Library/SmmCpuFeaturesLib/Amd/SmramSaveState.c > new file mode 100644 > index 000000000000..c1e7e6d6c6d9 > --- /dev/null > +++ b/UefiCpuPkg/Library/SmmCpuFeaturesLib/Amd/SmramSaveState.c > @@ -0,0 +1,409 @@ > +/** @file > +Provides services to access SMRAM Save State Map > + > +Copyright (c) 2010 - 2019, Intel Corporation. All rights reserved.
> +Copyright (C) 2022 Advanced Micro Devices, Inc. All rights reserved.
> +SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#include "SmramSaveState.h" > + > +// The mode of the CPU at the time an SMI occurs > +extern UINT8 mSmmSaveStateRegisterLma; > + > +// Table used by GetRegisterIndex() to convert an > EFI_SMM_SAVE_STATE_REGISTER > +// value to an index into a table of type CPU_SMM_SAVE_STATE_LOOKUP_ENTR= Y >=20 > +static CONST CPU_SMM_SAVE_STATE_REGISTER_RANGE mSmmCpuRegisterRanges[] = =3D > { > + 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 > +static CONST CPU_SMM_SAVE_STATE_LOOKUP_ENTRY mSmmCpuWidthOffset[] =3D { > + { 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 =3D 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 =3D 4 > + { 0, 8, 0, SMM_CPU_OFFSET (x64._IDTRBaseLoDword), SMM_CPU_OFFSET > (x64._IDTRBaseLoDword), FALSE}, // EFI_SMM_SAVE_STATE_REGISTER_IDTBASE = =3D 5 >=20 > + { 0, 8, 0, SMM_CPU_OFFSET (x64._LDTRBaseLoDword), SMM_CPU_OFFSET > (x64._LDTRBaseLoDword), FALSE}, // EFI_SMM_SAVE_STATE_REGISTER_LDTBASE = =3D 6 >=20 > + { 0, 2, 0, SMM_CPU_OFFSET (x64._GDTRLimit), 0, FALSE}, // > EFI_SMM_SAVE_STATE_REGISTER_GDTLIMIT =3D 7 > + { 0, 2, 0, SMM_CPU_OFFSET (x64._IDTRLimit), 0, FALSE}, // > EFI_SMM_SAVE_STATE_REGISTER_IDTLIMIT =3D 8 > + { 0, 4, 0, SMM_CPU_OFFSET (x64._LDTRLimit), 0, FALSE}, // > EFI_SMM_SAVE_STATE_REGISTER_LDTLIMIT =3D 9 > + { 0, 0, 0, 0, 0, FALSE}, // EFI_SMM_SAVE_STATE_REGISTER_LDTINFO =3D 10 > + { 4, 2, SMM_CPU_OFFSET (x86._ES), SMM_CPU_OFFSET (x64._ES), 0, FALSE}, > // EFI_SMM_SAVE_STATE_REGISTER_ES =3D 20 > + { 4, 2, SMM_CPU_OFFSET (x86._CS), SMM_CPU_OFFSET (x64._CS), 0, FALSE}, > // EFI_SMM_SAVE_STATE_REGISTER_CS =3D 21 > + { 4, 2, SMM_CPU_OFFSET (x86._SS), SMM_CPU_OFFSET (x64._SS), 0, FALSE}, > // EFI_SMM_SAVE_STATE_REGISTER_SS =3D 22 > + { 4, 2, SMM_CPU_OFFSET (x86._DS), SMM_CPU_OFFSET (x64._DS), 0, FALSE}, > // EFI_SMM_SAVE_STATE_REGISTER_DS =3D 23 > + { 4, 2, SMM_CPU_OFFSET (x86._FS), SMM_CPU_OFFSET (x64._FS), 0, FALSE}, > // EFI_SMM_SAVE_STATE_REGISTER_FS =3D 24 > + { 4, 2, SMM_CPU_OFFSET (x86._GS), SMM_CPU_OFFSET (x64._GS), 0, FALSE}, > // EFI_SMM_SAVE_STATE_REGISTER_GS =3D 25 > + { 0, 2, 0, SMM_CPU_OFFSET (x64._LDTR), 0, FALSE}, // > EFI_SMM_SAVE_STATE_REGISTER_LDTR_SEL =3D 26 > + { 0, 2, 0, SMM_CPU_OFFSET (x64._TR), 0, FALSE}, // > EFI_SMM_SAVE_STATE_REGISTER_TR_SEL =3D 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 > =3D 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 > =3D 29 > + { 0, 8, 0, SMM_CPU_OFFSET (x64._R8), SMM_CPU_OFFSET (x64._R8) + 4, > TRUE}, // EFI_SMM_SAVE_STATE_REGISTER_R8 =3D 30 > + { 0, 8, 0, SMM_CPU_OFFSET (x64._R9), SMM_CPU_OFFSET (x64._R9) + 4, > TRUE}, // EFI_SMM_SAVE_STATE_REGISTER_R9 =3D 31 > + { 0, 8, 0, SMM_CPU_OFFSET (x64._R10), SMM_CPU_OFFSET (x64._R10) + 4, > TRUE}, // EFI_SMM_SAVE_STATE_REGISTER_R10 =3D 32 > + { 0, 8, 0, SMM_CPU_OFFSET (x64._R11), SMM_CPU_OFFSET (x64._R11) + 4, > TRUE}, // EFI_SMM_SAVE_STATE_REGISTER_R11 =3D 33 > + { 0, 8, 0, SMM_CPU_OFFSET (x64._R12), SMM_CPU_OFFSET (x64._R12) + 4, > TRUE}, // EFI_SMM_SAVE_STATE_REGISTER_R12 =3D 34 > + { 0, 8, 0, SMM_CPU_OFFSET (x64._R13), SMM_CPU_OFFSET (x64._R13) + 4, > TRUE}, // EFI_SMM_SAVE_STATE_REGISTER_R13 =3D 35 > + { 0, 8, 0, SMM_CPU_OFFSET (x64._R14), SMM_CPU_OFFSET (x64._R14) + 4, > TRUE}, // EFI_SMM_SAVE_STATE_REGISTER_R14 =3D 36 > + { 0, 8, 0, SMM_CPU_OFFSET (x64._R15), SMM_CPU_OFFSET (x64._R15) + 4, > TRUE}, // EFI_SMM_SAVE_STATE_REGISTER_R15 =3D 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 = =3D > 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 = =3D > 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 = =3D > 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 = =3D > 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 = =3D > 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 = =3D > 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 = =3D > 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 = =3D > 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 = =3D > 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 =3D 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 > =3D 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 > =3D 53 > + { 0, 8, 0, SMM_CPU_OFFSET (x64._CR4), SMM_CPU_OFFSET (x64._CR4) + 4, > FALSE}, // EFI_SMM_SAVE_STATE_REGISTER_CR4 =3D 54 > + { 0, 0, 0, 0, 0 } > +}; > + > +/** > + 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 mSmmCpuWidthOffset[] associated with Register > + > +**/ > +STATIC > +UINTN > +EFIAPI > +GetRegisterIndex ( > + IN EFI_SMM_SAVE_STATE_REGISTER Register > + ) > +{ > + UINTN Index; > + UINTN Offset; > + > + for (Index =3D 0, Offset =3D SMM_SAVE_STATE_REGISTER_MAX_INDEX; > mSmmCpuRegisterRanges[Index].Length !=3D 0; Index++) { > + if ((Register >=3D mSmmCpuRegisterRanges[Index].Start) && (Register <= =3D > mSmmCpuRegisterRanges[Index].End)) { > + return Register - mSmmCpuRegisterRanges[Index].Start + Offset; > + } > + > + Offset +=3D mSmmCpuRegisterRanges[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 mSmmCpuWidthOffset[] 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. > + > +**/ > +STATIC > +EFI_STATUS > +EFIAPI > +ReadSaveStateRegisterByIndex ( > + IN UINTN CpuIndex, > + IN UINTN RegisterIndex, > + IN UINTN Width, > + OUT VOID *Buffer > + ) > +{ > + AMD_SMRAM_SAVE_STATE_MAP *CpuSaveState; > + > + // UINT32 SmmRevId; > + > + if (RegisterIndex =3D=3D 0) { > + return EFI_NOT_FOUND; > + } > + > + CpuSaveState =3D gSmst->CpuSaveState[CpuIndex]; > + // SmmRevId =3D CpuSaveState->x86.SMMRevId; > + > + if (mSmmSaveStateRegisterLma =3D=3D EFI_SMM_SAVE_STATE_REGISTER_LMA_32B= IT) { >=20 > + // > + // If 32-bit mode width is zero, then the specified register can not be > accessed > + // > + if (mSmmCpuWidthOffset[RegisterIndex].Width32 =3D=3D 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 > mSmmCpuWidthOffset[RegisterIndex].Width32) { > + return EFI_INVALID_PARAMETER; > + } > + > + // > + // Write return buffer > + // > + ASSERT (CpuSaveState !=3D NULL); > + CopyMem (Buffer, (UINT8 *)CpuSaveState + > mSmmCpuWidthOffset[RegisterIndex].Offset32, Width); > + } else { > + // > + // If 64-bit mode width is zero, then the specified register can not be > accessed > + // > + if (mSmmCpuWidthOffset[RegisterIndex].Width64 =3D=3D 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 > mSmmCpuWidthOffset[RegisterIndex].Width64) { > + return EFI_INVALID_PARAMETER; > + } > + > + // > + // Write lower 32-bits of return buffer > + // > + CopyMem (Buffer, (UINT8 *)CpuSaveState + > mSmmCpuWidthOffset[RegisterIndex].Offset64Lo, MIN (4, Width)); > + if (Width >=3D 4) { > + // > + // Write upper 32-bits of return buffer > + // > + CopyMem ((UINT8 *)Buffer + 4, (UINT8 *)CpuSaveState + > mSmmCpuWidthOffset[RegisterIndex].Offset64Hi, Width - 4); > + } > + } > + > + return EFI_SUCCESS; > +} > + > +/** > + 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. Th= e >=20 > + 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 Register= . >=20 > + > +**/ > +EFI_STATUS > +EFIAPI > +InternalSmmCpuFeaturesReadSaveStateRegister ( > + 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 =3D (AMD_SMRAM_SAVE_STATE_MAP > *)gSmst->CpuSaveState[CpuIndex]; > + > + // Check for special EFI_SMM_SAVE_STATE_REGISTER_LMA > + if (Register =3D=3D EFI_SMM_SAVE_STATE_REGISTER_LMA) { > + // Only byte access is supported for this register > + if (Width !=3D 1) { > + return EFI_INVALID_PARAMETER; > + } > + > + *(UINT8 *)Buffer =3D mSmmSaveStateRegisterLma; > + > + return EFI_SUCCESS; > + } > + > + // Check for special EFI_SMM_SAVE_STATE_REGISTER_IO > + > + if (Register =3D=3D EFI_SMM_SAVE_STATE_REGISTER_IO) { > + // > + // Get SMM Revision ID > + // > + ReadSaveStateRegisterByIndex (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 =3D (EFI_SMM_SAVE_STATE_IO_INFO *)Buffer; > + ZeroMem (IoInfo, sizeof (EFI_SMM_SAVE_STATE_IO_INFO)); > + > + IoInfo->IoPort =3D (UINT16)(CpuSaveState->x64.IO_DWord >> 16u); > + > + if (CpuSaveState->x64.IO_DWord & 0x10u) { > + IoInfo->IoWidth =3D EFI_SMM_SAVE_STATE_IO_WIDTH_UINT8; > + DataWidth =3D 0x01u; > + } else if (CpuSaveState->x64.IO_DWord & 0x20u) { > + IoInfo->IoWidth =3D EFI_SMM_SAVE_STATE_IO_WIDTH_UINT16; > + DataWidth =3D 0x02u; > + } else { > + IoInfo->IoWidth =3D EFI_SMM_SAVE_STATE_IO_WIDTH_UINT32; > + DataWidth =3D 0x04u; > + } > + > + if (CpuSaveState->x64.IO_DWord & 0x01u) { > + IoInfo->IoType =3D EFI_SMM_SAVE_STATE_IO_TYPE_INPUT; > + } else { > + IoInfo->IoType =3D EFI_SMM_SAVE_STATE_IO_TYPE_OUTPUT; > + } > + > + if ((IoInfo->IoType =3D=3D EFI_SMM_SAVE_STATE_IO_TYPE_INPUT) || > (IoInfo->IoType =3D=3D EFI_SMM_SAVE_STATE_IO_TYPE_OUTPUT)) { > + SmmCpuFeaturesReadSaveStateRegister (CpuIndex, > EFI_SMM_SAVE_STATE_REGISTER_RAX, DataWidth, &IoInfo->IoData); > + } > + > + return EFI_SUCCESS; > + } > + > + // Convert Register to a register lookup table index > + return ReadSaveStateRegisterByIndex (CpuIndex, GetRegisterIndex > (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 Register= . >=20 > +**/ > +EFI_STATUS > +EFIAPI > +InternalSmmCpuFeaturesWriteSaveStateRegister ( > + 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 =3D=3D EFI_SMM_SAVE_STATE_REGISTER_LMA) { > + return EFI_SUCCESS; > + } > + > + // > + // Writes to EFI_SMM_SAVE_STATE_REGISTER_IO are not supported > + // > + if (Register =3D=3D EFI_SMM_SAVE_STATE_REGISTER_IO) { > + return EFI_NOT_FOUND; > + } > + > + // > + // Convert Register to a register lookup table index > + // > + RegisterIndex =3D GetRegisterIndex (Register); > + if (RegisterIndex =3D=3D 0) { > + return EFI_NOT_FOUND; > + } > + > + CpuSaveState =3D gSmst->CpuSaveState[CpuIndex]; > + > + // > + // Do not write non-writable SaveState, because it will cause exception= . >=20 > + // > + if (!mSmmCpuWidthOffset[RegisterIndex].Writeable) { > + return EFI_UNSUPPORTED; > + } > + > + // > + // Check CPU mode > + // > + if (mSmmSaveStateRegisterLma =3D=3D EFI_SMM_SAVE_STATE_REGISTER_LMA_32B= IT) { >=20 > + // > + // If 32-bit mode width is zero, then the specified register can not be > accessed > + // > + if (mSmmCpuWidthOffset[RegisterIndex].Width32 =3D=3D 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 > mSmmCpuWidthOffset[RegisterIndex].Width32) { > + return EFI_INVALID_PARAMETER; > + } > + > + // > + // Write SMM State register > + // > + ASSERT (CpuSaveState !=3D NULL); > + CopyMem ((UINT8 *)CpuSaveState + > mSmmCpuWidthOffset[RegisterIndex].Offset32, Buffer, Width); > + } else { > + // > + // If 64-bit mode width is zero, then the specified register can not be > accessed > + // > + if (mSmmCpuWidthOffset[RegisterIndex].Width64 =3D=3D 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 > mSmmCpuWidthOffset[RegisterIndex].Width64) { > + return EFI_INVALID_PARAMETER; > + } > + > + // > + // Write lower 32-bits of SMM State register > + // > + CopyMem ((UINT8 *)CpuSaveState + > mSmmCpuWidthOffset[RegisterIndex].Offset64Lo, Buffer, MIN (4, Width)); > + if (Width >=3D 4) { > + // > + // Write upper 32-bits of SMM State register > + // > + CopyMem ((UINT8 *)CpuSaveState + > mSmmCpuWidthOffset[RegisterIndex].Offset64Hi, (UINT8 *)Buffer + 4, Width = - > 4); > + } > + } > + > + return EFI_SUCCESS; > +} > -- > 2.25.1 --deqQsT29TNeltRygQVqk Content-Type: text/html; charset="utf-8" Content-Transfer-Encoding: quoted-printable Hi Abdul,
This is a little bit confusing because there is one SmramSav= eStae.c under PismmCpuDxeSmm however another one is under SmmCpuFeaturesLib= for AMD.
I would suggest we introduce SmramSaveState library under Ue= fiCpuPkg/Library which is used by both PismmCpuDxeSmm and SmmCpuFeatur= esLib. This makes the library reference clear without duplication.
We = can have AMD SmramSaveStateLib instance and just name it as SmramSaveStateL= ib.c. That is Intel's decision if they want to move their implementation fr= om PismmCpuDxeSmm to SmramSaveState or not.
Thanks
Abner

On Tue, Dec 6, 2022 at 09:23 PM, Abdul Lateef Attar wrote:
From: Abdul Lateef Attar <AbdulLateef.Attar@amd.com>

BZ: https://bugzilla.tianocore.org/show_bu= g.cgi?id=3D4182

Implements interfaces to read and write save= state
registers of AMD's processor family.
Initializes processor= SMMADDR and MASK depends
on PcdSmrrEnable flag.
Program or corre= cts the IP once control returns from SMM.

Cc: Paul Grimes <pa= ul.grimes@amd.com>
Cc: Garrett Kirkendall <garrett.kirkendall@am= d.com>
Cc: Abner Chang <abner.chang@amd.com>
Cc: Eric Do= ng <eric.dong@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
Cc: Rahul Kumar <rahul1.kumar@intel.com>
Signed-off-by: Abdul = Lateef Attar <AbdulLateef.Attar@amd.com>
---
.../AmdSmmCpuF= eaturesLib.inf | 2 +
.../SmmCpuFeaturesLib/Amd/SmramSaveState.h | 109 = +++++
.../SmmCpuFeaturesLib/Amd/SmmCpuFeaturesLib.c | 97 ++++-
..= ./SmmCpuFeaturesLib/Amd/SmramSaveState.c | 409 ++++++++++++++++++
4 fi= les changed, 612 insertions(+), 5 deletions(-)
create mode 100644 Uefi= CpuPkg/Library/SmmCpuFeaturesLib/Amd/SmramSaveState.h
create mode 1006= 44 UefiCpuPkg/Library/SmmCpuFeaturesLib/Amd/SmramSaveState.c

dif= f --git a/UefiCpuPkg/Library/SmmCpuFeaturesLib/AmdSmmCpuFeaturesLib.inf b/U= efiCpuPkg/Library/SmmCpuFeaturesLib/AmdSmmCpuFeaturesLib.inf
index 08a= c0262022f..95eb31d16ead 100644
--- a/UefiCpuPkg/Library/SmmCpuFeatures= Lib/AmdSmmCpuFeaturesLib.inf
+++ b/UefiCpuPkg/Library/SmmCpuFeaturesLi= b/AmdSmmCpuFeaturesLib.inf
@@ -21,6 +21,8 @@ [Sources]
SmmCpuFeat= uresLib.c
SmmCpuFeaturesLibCommon.c
Amd/SmmCpuFeaturesLib.c
= + Amd/SmramSaveState.c
+ Amd/SmramSaveState.h

[Packages]MdePkg/MdePkg.dec
diff --git a/UefiCpuPkg/Library/SmmCpuFeaturesLib= /Amd/SmramSaveState.h b/UefiCpuPkg/Library/SmmCpuFeaturesLib/Amd/SmramSaveS= tate.h
new file mode 100644
index 000000000000..290ebdbc9227
--- /dev/null
+++ b/UefiCpuPkg/Library/SmmCpuFeaturesLib/Amd/SmramSav= eState.h
@@ -0,0 +1,109 @@
+/** @file
+SMRAM Save State Map = header file.
+
+Copyright (c) 2010 - 2019, Intel Corporation. All= rights reserved.<BR>
+Copyright (C) 2022 Advanced Micro Devices= , Inc. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-= Clause-Patent
+
+**/
+
+#ifndef SMRAM_SAVESTATE_H_
+#define SMRAM_SAVESTATE_H_
+
+#include <Library/SmmCpuFeatur= esLib.h>
+#include <Library/BaseLib.h>
+#include <Lib= rary/BaseMemoryLib.h>
+#include <Library/PcdLib.h>
+#inc= lude <Library/DebugLib.h>
+#include <Library/SmmServicesTable= Lib.h>
+#include <Register/Amd/SmramSaveStateMap.h>
++// EFER register LMA bit
+#define LMA BIT10
+
+// Machin= e Specific Registers (MSRs)
+#define SMMADDR_ADDRESS 0xC0010112ul
+#define SMMMASK_ADDRESS 0xC0010113ul
+#define EFER_ADDRESS 0XC000008= 0ul
+
+// 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)
+
+// Macro used to simplif= y the lookup table entries of type CPU_SMM_SAVE_STATE_REGISTER_RANGE
+= #define SMM_REGISTER_RANGE(Start, End) { Start, End, End - Start + 1 }
+
+// Structure used to describe a range of registers
+typedef s= truct {
+ EFI_SMM_SAVE_STATE_REGISTER Start;
+ EFI_SMM_SAVE_STATE= _REGISTER End;
+ UINTN Length;
+} CPU_SMM_SAVE_STATE_REGISTER_RAN= GE;
+
+// Structure used to build a lookup table to retrieve the = widths and offsets
+// associated with each supported EFI_SMM_SAVE_STA= TE_REGISTER value
+
+#define SMM_SAVE_STATE_REGISTER_SMMREVID_IND= EX 1
+#define SMM_SAVE_STATE_REGISTER_MAX_INDEX 2
+
+typedef= struct {
+ UINT8 Width32;
+ UINT8 Width64;
+ UINT16 Offset3= 2;
+ UINT16 Offset64Lo;
+ UINT16 Offset64Hi;
+ BOOLEAN Write= able;
+} CPU_SMM_SAVE_STATE_LOOKUP_ENTRY;
+
+/**
+ 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 o= f the CPU to read the SMM Save State. The
+ value must be between 0 an= d 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.<= br />+ @retval EFI_UNSUPPORTED This function does not support reading Regis= ter.
+
+**/
+EFI_STATUS
+EFIAPI
+InternalSmmCpuFea= turesReadSaveStateRegister (
+ IN UINTN CpuIndex,
+ IN EFI_SMM_SA= VE_STATE_REGISTER Register,
+ IN UINTN Width,
+ OUT VOID *Buffer<= br />+ );
+
+/**
+ 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 Sta= te. 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 byt= es to write to the CPU save state.
+ @param[in] Buffer Upon entry, thi= s holds the new CPU register value.
+
+ @retval EFI_SUCCESS The r= egister was written to Save State.
+ @retval EFI_INVALID_PARAMTER Buff= er is NULL.
+ @retval EFI_UNSUPPORTED This function does not support w= riting Register.
+**/
+EFI_STATUS
+EFIAPI
+InternalSmmC= puFeaturesWriteSaveStateRegister (
+ IN UINTN CpuIndex,
+ IN EFI_= SMM_SAVE_STATE_REGISTER Register,
+ IN UINTN Width,
+ IN CONST VO= ID *Buffer
+ );
+
+#endif
diff --git a/UefiCpuPkg/Libra= ry/SmmCpuFeaturesLib/Amd/SmmCpuFeaturesLib.c b/UefiCpuPkg/Library/SmmCpuFea= turesLib/Amd/SmmCpuFeaturesLib.c
index dc3fed0302d2..10bed4116397 1006= 44
--- a/UefiCpuPkg/Library/SmmCpuFeaturesLib/Amd/SmmCpuFeaturesLib.c<= br />+++ b/UefiCpuPkg/Library/SmmCpuFeaturesLib/Amd/SmmCpuFeaturesLib.c
@@ -9,8 +9,10 @@ SPDX-License-Identifier: BSD-2-Clause-Patent

= **/

-#include <Library/SmmCpuFeaturesLib.h>
-#include= <Uefi/UefiBaseType.h>
+#include "SmramSaveState.h"
+
= +// The mode of the CPU at the time an SMI occurs
+extern UINT8 mSmmSa= veStateRegisterLma;

/**
Read an SMM Save State register on = the target processor. If this function
@@ -39,7 +41,7 @@ SmmCpuFeature= sReadSaveStateRegister (
OUT VOID *Buffer
)
{
- return = EFI_SUCCESS;
+ return InternalSmmCpuFeaturesReadSaveStateRegister (Cpu= Index, Register, Width, Buffer);
}

/**
@@ -67,7 +69,7 = @@ SmmCpuFeaturesWriteSaveStateRegister (
IN CONST VOID *Buffer
)=
{
- return EFI_SUCCESS;
+ return InternalSmmCpuFeaturesWrit= eSaveStateRegister (CpuIndex, Register, Width, Buffer);
}

/= **
@@ -82,6 +84,13 @@ CpuFeaturesLibInitialization (
VOID
)<= br />{
+ UINT32 LMAValue;
+
+ LMAValue =3D (UINT32)AsmReadMs= r64 (EFER_ADDRESS) & LMA;
+ mSmmSaveStateRegisterLma =3D EFI_SMM_S= AVE_STATE_REGISTER_LMA_32BIT;
+ if (LMAValue) {
+ mSmmSaveStateRe= gisterLma =3D EFI_SMM_SAVE_STATE_REGISTER_LMA_64BIT;
+ }
}
<= br />/**
@@ -117,6 +126,52 @@ SmmCpuFeaturesInitializeProcessor (
IN CPU_HOT_PLUG_DATA *CpuHotPlugData
)
{
+ AMD_SMRAM_SAVE_S= TATE_MAP *CpuState;
+ UINT32 LMAValue;
+
+ //
+ // Conf= igure SMBASE.
+ //
+ CpuState =3D (AMD_SMRAM_SAVE_STATE_MAP *)(UI= NTN)(SMM_DEFAULT_SMBASE + SMRAM_SAVE_STATE_MAP_OFFSET);
+ CpuState->= ;x64.SMBASE =3D (UINT32)CpuHotPlugData->SmBase[CpuIndex];
+
+ = // Re-initialize the value of mSmmSaveStateRegisterLma flag which might hav= e been changed in PiCpuSmmDxeSmm Driver
+ // Entry point, to make sure= correct value on AMD platform is assigned to be used by SmmCpuFeaturesLib.=
+ LMAValue =3D (UINT32)AsmReadMsr64 (EFER_ADDRESS) & LMA;
+ = mSmmSaveStateRegisterLma =3D EFI_SMM_SAVE_STATE_REGISTER_LMA_32BIT;
+ = if (LMAValue) {
+ mSmmSaveStateRegisterLma =3D EFI_SMM_SAVE_STATE_REGI= STER_LMA_64BIT;
+ }
+
+ //
+ // If SMRR is supported, t= hen program SMRR base/mask MSRs.
+ // The EFI_MSR_SMRR_PHYS_MASK_VALID= bit is not set until the first normal SMI.
+ // The code that initial= izes SMM environment is running in normal mode
+ // from SMRAM region.= If SMRR is enabled here, then the SMRAM region
+ // is protected and = the normal mode code execution will fail.
+ //
+ if (FeaturePcdGe= t (PcdSmrrEnable)) {
+ //
+ // SMRR size cannot be less than 4-KB= ytes
+ // SMRR size must be of length 2^n
+ // SMRR base alignmen= t cannot be less than SMRR length
+ //
+ if ((CpuHotPlugData->= SmrrSize < SIZE_4KB) ||
+ (CpuHotPlugData->SmrrSize !=3D GetPowe= rOfTwo32 (CpuHotPlugData->SmrrSize)) ||
+ ((CpuHotPlugData->Smrr= Base & ~(CpuHotPlugData->SmrrSize - 1)) !=3D CpuHotPlugData->Smrr= Base))
+ {
+ //
+ // Print message and halt if CPU is Monarc= h
+ //
+ if (IsMonarch) {
+ DEBUG ((DEBUG_ERROR, "SMM Base/S= ize does not meet alignment/size requirement!\n"));
+ CpuDeadLoop ();<= br />+ }
+ } else {
+ AsmWriteMsr64 (SMMADDR_ADDRESS, CpuHotPlugD= ata->SmrrBase);
+ AsmWriteMsr64 (SMMMASK_ADDRESS, ((~(UINT64)(CpuHo= tPlugData->SmrrSize - 1)) | 0x6600));
+ }
+ }
}

/**
@@ -159,7 +214,39 @@ SmmCpuFeaturesHookReturnFromSmm (
IN U= INT64 NewInstructionPointer
)
{
- return 0;
+ UINT64 Or= iginalInstructionPointer;
+ AMD_SMRAM_SAVE_STATE_MAP *AmdCpuState;
+
+ AmdCpuState =3D (AMD_SMRAM_SAVE_STATE_MAP *)CpuState;
+
+ if (mSmmSaveStateRegisterLma =3D=3D EFI_SMM_SAVE_STATE_REGISTER_LMA_32B= IT) {
+ OriginalInstructionPointer =3D (UINT64)AmdCpuState->x86._EI= P;
+ AmdCpuState->x86._EIP =3D (UINT32)NewInstructionPointer;
= + //
+ // Clear the auto HALT restart flag so the RSM instruction retu= rns
+ // program control to the instruction following the HLT instruct= ion.
+ //
+ if ((AmdCpuState->x86.AutoHALTRestart & BIT0) = !=3D 0) {
+ AmdCpuState->x86.AutoHALTRestart &=3D ~BIT0;
+= }
+ } else {
+ OriginalInstructionPointer =3D AmdCpuState->x6= 4._RIP;
+ if ((AmdCpuState->x64.EFER & LMA) =3D=3D 0) {
+ = AmdCpuState->x64._RIP =3D (UINT32)NewInstructionPointer32;
+ } else= {
+ AmdCpuState->x64._RIP =3D (UINT32)NewInstructionPointer;
= + }
+
+ //
+ // Clear the auto HALT restart flag so the RSM = instruction returns
+ // program control to the instruction following = the HLT instruction.
+ //
+ if ((AmdCpuState->x64.AutoHALTRest= art & BIT0) !=3D 0) {
+ AmdCpuState->x64.AutoHALTRestart &= =3D ~BIT0;
+ }
+ }
+
+ return OriginalInstructionPointe= r;
}

/**
diff --git a/UefiCpuPkg/Library/SmmCpuFeature= sLib/Amd/SmramSaveState.c b/UefiCpuPkg/Library/SmmCpuFeaturesLib/Amd/SmramS= aveState.c
new file mode 100644
index 000000000000..c1e7e6d6c6d9<= br />--- /dev/null
+++ b/UefiCpuPkg/Library/SmmCpuFeaturesLib/Amd/Smra= mSaveState.c
@@ -0,0 +1,409 @@
+/** @file
+Provides services= to access SMRAM Save State Map
+
+Copyright (c) 2010 - 2019, Int= el Corporation. All rights reserved.<BR>
+Copyright (C) 2022 Adv= anced Micro Devices, Inc. All rights reserved.<BR>
+SPDX-License= -Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "Sm= ramSaveState.h"
+
+// The mode of the CPU at the time an SMI occu= rs
+extern UINT8 mSmmSaveStateRegisterLma;
+
+// Table used = by GetRegisterIndex() to convert an EFI_SMM_SAVE_STATE_REGISTER
+// va= lue to an index into a table of type CPU_SMM_SAVE_STATE_LOOKUP_ENTRY
+= static CONST CPU_SMM_SAVE_STATE_REGISTER_RANGE mSmmCpuRegisterRanges[] =3D = {
+ SMM_REGISTER_RANGE (EFI_SMM_SAVE_STATE_REGISTER_GDTBASE, EFI_SMM_S= AVE_STATE_REGISTER_LDTINFO),
+ SMM_REGISTER_RANGE (EFI_SMM_SAVE_STATE_= REGISTER_ES, EFI_SMM_SAVE_STATE_REGISTER_RIP),
+ SMM_REGISTER_RANGE (E= FI_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 as= sociated with each
+// supported EFI_SMM_SAVE_STATE_REGISTER value
+static CONST CPU_SMM_SAVE_STATE_LOOKUP_ENTRY mSmmCpuWidthOffset[] =3D {<= br />+ { 0, 0, 0, 0, FALSE }, // Reserved
+
+ //
+ // Intern= ally defined CPU Save State Registers. Not defined in PI SMM CPU Protocol.<= br />+ //
+ { 4, 4, SMM_CPU_OFFSET (x86.SMMRevId), SMM_CPU_OFFSET (x64= .SMMRevId), 0, FALSE}, // SMM_SAVE_STATE_REGISTER_SMMREVID_INDEX =3D 1
+
+ //
+ // CPU Save State registers defined in PI SMM CPU Proto= col.
+ //
+ { 4, 8, SMM_CPU_OFFSET (x86.GDTBase), SMM_CPU_OFFSET = (x64._GDTRBaseLoDword), SMM_CPU_OFFSET (x64._GDTRBaseHiDword), FALSE}, // E= FI_SMM_SAVE_STATE_REGISTER_GDTBASE =3D 4
+ { 0, 8, 0, SMM_CPU_OFFSET (= x64._IDTRBaseLoDword), SMM_CPU_OFFSET (x64._IDTRBaseLoDword), FALSE}, // EF= I_SMM_SAVE_STATE_REGISTER_IDTBASE =3D 5
+ { 0, 8, 0, SMM_CPU_OFFSET (x= 64._LDTRBaseLoDword), SMM_CPU_OFFSET (x64._LDTRBaseLoDword), FALSE}, // EFI= _SMM_SAVE_STATE_REGISTER_LDTBASE =3D 6
+ { 0, 2, 0, SMM_CPU_OFFSET (x6= 4._GDTRLimit), 0, FALSE}, // EFI_SMM_SAVE_STATE_REGISTER_GDTLIMIT =3D 7
+ { 0, 2, 0, SMM_CPU_OFFSET (x64._IDTRLimit), 0, FALSE}, // EFI_SMM_SAVE_= STATE_REGISTER_IDTLIMIT =3D 8
+ { 0, 4, 0, SMM_CPU_OFFSET (x64._LDTRLi= mit), 0, FALSE}, // EFI_SMM_SAVE_STATE_REGISTER_LDTLIMIT =3D 9
+ { 0, = 0, 0, 0, 0, FALSE}, // EFI_SMM_SAVE_STATE_REGISTER_LDTINFO =3D 10
+ { = 4, 2, SMM_CPU_OFFSET (x86._ES), SMM_CPU_OFFSET (x64._ES), 0, FALSE}, // EFI= _SMM_SAVE_STATE_REGISTER_ES =3D 20
+ { 4, 2, SMM_CPU_OFFSET (x86._CS),= SMM_CPU_OFFSET (x64._CS), 0, FALSE}, // EFI_SMM_SAVE_STATE_REGISTER_CS =3D= 21
+ { 4, 2, SMM_CPU_OFFSET (x86._SS), SMM_CPU_OFFSET (x64._SS), 0, F= ALSE}, // EFI_SMM_SAVE_STATE_REGISTER_SS =3D 22
+ { 4, 2, SMM_CPU_OFFS= ET (x86._DS), SMM_CPU_OFFSET (x64._DS), 0, FALSE}, // EFI_SMM_SAVE_STATE_RE= GISTER_DS =3D 23
+ { 4, 2, SMM_CPU_OFFSET (x86._FS), SMM_CPU_OFFSET (x= 64._FS), 0, FALSE}, // EFI_SMM_SAVE_STATE_REGISTER_FS =3D 24
+ { 4, 2,= SMM_CPU_OFFSET (x86._GS), SMM_CPU_OFFSET (x64._GS), 0, FALSE}, // EFI_SMM_= SAVE_STATE_REGISTER_GS =3D 25
+ { 0, 2, 0, SMM_CPU_OFFSET (x64._LDTR),= 0, FALSE}, // EFI_SMM_SAVE_STATE_REGISTER_LDTR_SEL =3D 26
+ { 0, 2, 0= , SMM_CPU_OFFSET (x64._TR), 0, FALSE}, // EFI_SMM_SAVE_STATE_REGISTER_TR_SE= L =3D 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_DR= 7 =3D 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_DR= 6 =3D 29
+ { 0, 8, 0, SMM_CPU_OFFSET (x64._R8), SMM_CPU_OFFSET (x64._R= 8) + 4, TRUE}, // EFI_SMM_SAVE_STATE_REGISTER_R8 =3D 30
+ { 0, 8, 0, S= MM_CPU_OFFSET (x64._R9), SMM_CPU_OFFSET (x64._R9) + 4, TRUE}, // EFI_SMM_SA= VE_STATE_REGISTER_R9 =3D 31
+ { 0, 8, 0, SMM_CPU_OFFSET (x64._R10), SM= M_CPU_OFFSET (x64._R10) + 4, TRUE}, // EFI_SMM_SAVE_STATE_REGISTER_R10 =3D = 32
+ { 0, 8, 0, SMM_CPU_OFFSET (x64._R11), SMM_CPU_OFFSET (x64._R11) += 4, TRUE}, // EFI_SMM_SAVE_STATE_REGISTER_R11 =3D 33
+ { 0, 8, 0, SMM_= CPU_OFFSET (x64._R12), SMM_CPU_OFFSET (x64._R12) + 4, TRUE}, // EFI_SMM_SAV= E_STATE_REGISTER_R12 =3D 34
+ { 0, 8, 0, SMM_CPU_OFFSET (x64._R13), SM= M_CPU_OFFSET (x64._R13) + 4, TRUE}, // EFI_SMM_SAVE_STATE_REGISTER_R13 =3D = 35
+ { 0, 8, 0, SMM_CPU_OFFSET (x64._R14), SMM_CPU_OFFSET (x64._R14) += 4, TRUE}, // EFI_SMM_SAVE_STATE_REGISTER_R14 =3D 36
+ { 0, 8, 0, SMM_= CPU_OFFSET (x64._R15), SMM_CPU_OFFSET (x64._R15) + 4, TRUE}, // EFI_SMM_SAV= E_STATE_REGISTER_R15 =3D 37
+ { 4, 8, SMM_CPU_OFFSET (x86._EAX), SMM_C= PU_OFFSET (x64._RAX), SMM_CPU_OFFSET (x64._RAX) + 4, TRUE}, // EFI_SMM_SAVE= _STATE_REGISTER_RAX =3D 38
+ { 4, 8, SMM_CPU_OFFSET (x86._EBX), SMM_CP= U_OFFSET (x64._RBX), SMM_CPU_OFFSET (x64._RBX) + 4, TRUE}, // EFI_SMM_SAVE_= STATE_REGISTER_RBX =3D 39
+ { 4, 8, SMM_CPU_OFFSET (x86._ECX), SMM_CPU= _OFFSET (x64._RCX), SMM_CPU_OFFSET (x64._RCX) + 4, TRUE}, // EFI_SMM_SAVE_S= TATE_REGISTER_RBX =3D 39
+ { 4, 8, SMM_CPU_OFFSET (x86._EDX), SMM_CPU_= OFFSET (x64._RDX), SMM_CPU_OFFSET (x64._RDX) + 4, TRUE}, // EFI_SMM_SAVE_ST= ATE_REGISTER_RDX =3D 41
+ { 4, 8, SMM_CPU_OFFSET (x86._ESP), SMM_CPU_O= FFSET (x64._RSP), SMM_CPU_OFFSET (x64._RSP) + 4, TRUE}, // EFI_SMM_SAVE_STA= TE_REGISTER_RSP =3D 42
+ { 4, 8, SMM_CPU_OFFSET (x86._EBP), SMM_CPU_OF= FSET (x64._RBP), SMM_CPU_OFFSET (x64._RBP) + 4, TRUE}, // EFI_SMM_SAVE_STAT= E_REGISTER_RBP =3D 43
+ { 4, 8, SMM_CPU_OFFSET (x86._ESI), SMM_CPU_OFF= SET (x64._RSI), SMM_CPU_OFFSET (x64._RSI) + 4, TRUE}, // EFI_SMM_SAVE_STATE= _REGISTER_RSI =3D 44
+ { 4, 8, SMM_CPU_OFFSET (x86._EDI), SMM_CPU_OFFS= ET (x64._RDI), SMM_CPU_OFFSET (x64._RDI) + 4, TRUE}, // EFI_SMM_SAVE_STATE_= REGISTER_RDI =3D 45
+ { 4, 8, SMM_CPU_OFFSET (x86._EIP), SMM_CPU_OFFSE= T (x64._RIP), SMM_CPU_OFFSET (x64._RIP) + 4, TRUE}, // EFI_SMM_SAVE_STATE_R= EGISTER_RIP =3D 46
+
+ { 4, 8, SMM_CPU_OFFSET (x86._EFLAGS), SMM_= CPU_OFFSET (x64._RFLAGS), SMM_CPU_OFFSET (x64._RFLAGS) + 4, TRUE}, // EFI_S= MM_SAVE_STATE_REGISTER_RFLAGS =3D 51
+ { 4, 8, SMM_CPU_OFFSET (x86._CR= 0), SMM_CPU_OFFSET (x64._CR0), SMM_CPU_OFFSET (x64._CR0) + 4, FALSE}, // EF= I_SMM_SAVE_STATE_REGISTER_CR0 =3D 52
+ { 4, 8, SMM_CPU_OFFSET (x86._CR= 3), SMM_CPU_OFFSET (x64._CR3), SMM_CPU_OFFSET (x64._CR3) + 4, FALSE}, // EF= I_SMM_SAVE_STATE_REGISTER_CR3 =3D 53
+ { 0, 8, 0, SMM_CPU_OFFSET (x64.= _CR4), SMM_CPU_OFFSET (x64._CR4) + 4, FALSE}, // EFI_SMM_SAVE_STATE_REGISTE= R_CR4 =3D 54
+ { 0, 0, 0, 0, 0 }
+};
+
+/**
+ Read= information from the CPU save state.
+
+ @param Register Specifi= es the CPU register to read form the save state.
+
+ @retval 0 Re= gister is not valid
+ @retval >0 Index into mSmmCpuWidthOffset[] as= sociated with Register
+
+**/
+STATIC
+UINTN
+EFIA= PI
+GetRegisterIndex (
+ IN EFI_SMM_SAVE_STATE_REGISTER Register<= br />+ )
+{
+ UINTN Index;
+ UINTN Offset;
+
+ for= (Index =3D 0, Offset =3D SMM_SAVE_STATE_REGISTER_MAX_INDEX; mSmmCpuRegiste= rRanges[Index].Length !=3D 0; Index++) {
+ if ((Register >=3D mSmmC= puRegisterRanges[Index].Start) && (Register <=3D mSmmCpuRegister= Ranges[Index].End)) {
+ return Register - mSmmCpuRegisterRanges[Index]= .Start + Offset;
+ }
+
+ Offset +=3D mSmmCpuRegisterRanges[I= ndex].Length;
+ }
+
+ return 0;
+}
+
+/**
+ Read a CPU Save State register on the target processor.
+
+ T= his function abstracts the differences that whether the CPU Save State regi= ster is in the
+ IA32 CPU Save State Map or X64 CPU Save State Map.+
+ This function supports reading a CPU Save State register in SMB= ase relocation handler.
+
+ @param[in] CpuIndex Specifies the zer= o-based index of the CPU save state.
+ @param[in] RegisterIndex Index = into mSmmCpuWidthOffset[] look up table.
+ @param[in] Width The number= of bytes to read from the CPU save state.
+ @param[out] Buffer Upon r= eturn, this holds the CPU register value read from the save state.
++ @retval EFI_SUCCESS The register was read from Save State.
+ @re= tval EFI_NOT_FOUND The register is not defined for the Save State of Proces= sor.
+ @retval EFI_INVALID_PARAMTER This or Buffer is NULL.
+
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+ReadSaveStateRegist= erByIndex (
+ IN UINTN CpuIndex,
+ IN UINTN RegisterIndex,
+= IN UINTN Width,
+ OUT VOID *Buffer
+ )
+{
+ AMD_SMRAM_= SAVE_STATE_MAP *CpuSaveState;
+
+ // UINT32 SmmRevId;
+
+ if (RegisterIndex =3D=3D 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ CpuSaveState =3D gSmst->CpuSaveState[CpuIndex];
+ // SmmR= evId =3D CpuSaveState->x86.SMMRevId;
+
+ if (mSmmSaveStateRegi= sterLma =3D=3D EFI_SMM_SAVE_STATE_REGISTER_LMA_32BIT) {
+ //
+ //= If 32-bit mode width is zero, then the specified register can not be acces= sed
+ //
+ if (mSmmCpuWidthOffset[RegisterIndex].Width32 =3D=3D 0= ) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // If Wid= th is bigger than the 32-bit mode width, then the specified register can no= t be accessed
+ //
+ if (Width > mSmmCpuWidthOffset[RegisterIn= dex].Width32) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+= //
+ // Write return buffer
+ //
+ ASSERT (CpuSaveState != =3D NULL);
+ CopyMem (Buffer, (UINT8 *)CpuSaveState + mSmmCpuWidthOffs= et[RegisterIndex].Offset32, Width);
+ } else {
+ //
+ // If = 64-bit mode width is zero, then the specified register can not be accessed<= br />+ //
+ if (mSmmCpuWidthOffset[RegisterIndex].Width64 =3D=3D 0) {<= br />+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // If Width i= s bigger than the 64-bit mode width, then the specified register can not be= accessed
+ //
+ if (Width > mSmmCpuWidthOffset[RegisterIndex]= .Width64) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //<= br />+ // Write lower 32-bits of return buffer
+ //
+ CopyMem (Bu= ffer, (UINT8 *)CpuSaveState + mSmmCpuWidthOffset[RegisterIndex].Offset64Lo,= MIN (4, Width));
+ if (Width >=3D 4) {
+ //
+ // Write u= pper 32-bits of return buffer
+ //
+ CopyMem ((UINT8 *)Buffer + 4= , (UINT8 *)CpuSaveState + mSmmCpuWidthOffset[RegisterIndex].Offset64Hi, Wid= th - 4);
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+=
+/**
+ Read an SMM Save State register on the target processor. = If this function
+ returns EFI_UNSUPPORTED, then the caller is respons= ible for reading the
+ SMM Save Sate register.
+
+ @param[in= ] CpuIndex The index of the CPU to read the SMM Save State. The
+ valu= e must be between 0 and the NumberOfCpus field in
+ the System Managem= ent System Table (SMST).
+ @param[in] Register The SMM Save State regi= ster 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 r= egister value read
+ from the save state.
+
+ @retval EFI_SU= CCESS The register was read from Save State.
+ @retval EFI_INVALID_PAR= AMTER Buffer is NULL.
+ @retval EFI_UNSUPPORTED This function does not= support reading Register.
+
+**/
+EFI_STATUS
+EFIAPI+InternalSmmCpuFeaturesReadSaveStateRegister (
+ IN UINTN CpuIndex= ,
+ IN EFI_SMM_SAVE_STATE_REGISTER Register,
+ IN UINTN Width,+ OUT VOID *Buffer
+ )
+{
+ UINT32 SmmRevId;
+ EFI_S= MM_SAVE_STATE_IO_INFO *IoInfo;
+ AMD_SMRAM_SAVE_STATE_MAP *CpuSaveStat= e;
+ UINT8 DataWidth;
+
+ // Read CPU State
+ CpuSaveSt= ate =3D (AMD_SMRAM_SAVE_STATE_MAP *)gSmst->CpuSaveState[CpuIndex];
= +
+ // Check for special EFI_SMM_SAVE_STATE_REGISTER_LMA
+ if (Re= gister =3D=3D EFI_SMM_SAVE_STATE_REGISTER_LMA) {
+ // Only byte access= is supported for this register
+ if (Width !=3D 1) {
+ return EF= I_INVALID_PARAMETER;
+ }
+
+ *(UINT8 *)Buffer =3D mSmmSaveSt= ateRegisterLma;
+
+ return EFI_SUCCESS;
+ }
+
+ //= Check for special EFI_SMM_SAVE_STATE_REGISTER_IO
+
+ if (Registe= r =3D=3D EFI_SMM_SAVE_STATE_REGISTER_IO) {
+ //
+ // Get SMM Revi= sion ID
+ //
+ ReadSaveStateRegisterByIndex (CpuIndex, SMM_SAVE_S= TATE_REGISTER_SMMREVID_INDEX, sizeof (SmmRevId), &SmmRevId);
+
+ //
+ // See if the CPU supports the IOMisc register in the save st= ate
+ //
+ if (SmmRevId < AMD_SMM_MIN_REV_ID_X64) {
+ ret= urn EFI_NOT_FOUND;
+ }
+
+ // Check if IO Restart Dword [IO = Trap] is valid or not using bit 1.
+ if (!(CpuSaveState->x64.IO_DWo= rd & 0x02u)) {
+ return EFI_NOT_FOUND;
+ }
+
+ // Z= ero the IoInfo structure that will be returned in Buffer
+ IoInfo =3D = (EFI_SMM_SAVE_STATE_IO_INFO *)Buffer;
+ ZeroMem (IoInfo, sizeof (EFI_S= MM_SAVE_STATE_IO_INFO));
+
+ IoInfo->IoPort =3D (UINT16)(CpuSa= veState->x64.IO_DWord >> 16u);
+
+ if (CpuSaveState->= x64.IO_DWord & 0x10u) {
+ IoInfo->IoWidth =3D EFI_SMM_SAVE_STAT= E_IO_WIDTH_UINT8;
+ DataWidth =3D 0x01u;
+ } else if (CpuSaveStat= e->x64.IO_DWord & 0x20u) {
+ IoInfo->IoWidth =3D EFI_SMM_SAV= E_STATE_IO_WIDTH_UINT16;
+ DataWidth =3D 0x02u;
+ } else {
+= IoInfo->IoWidth =3D EFI_SMM_SAVE_STATE_IO_WIDTH_UINT32;
+ DataWidt= h =3D 0x04u;
+ }
+
+ if (CpuSaveState->x64.IO_DWord &= 0x01u) {
+ IoInfo->IoType =3D EFI_SMM_SAVE_STATE_IO_TYPE_INPUT;+ } else {
+ IoInfo->IoType =3D EFI_SMM_SAVE_STATE_IO_TYPE_OUTPU= T;
+ }
+
+ if ((IoInfo->IoType =3D=3D EFI_SMM_SAVE_STATE_= IO_TYPE_INPUT) || (IoInfo->IoType =3D=3D EFI_SMM_SAVE_STATE_IO_TYPE_OUTP= UT)) {
+ SmmCpuFeaturesReadSaveStateRegister (CpuIndex, EFI_SMM_SAVE_S= TATE_REGISTER_RAX, DataWidth, &IoInfo->IoData);
+ }
+
+ return EFI_SUCCESS;
+ }
+
+ // Convert Register to a regi= ster lookup table index
+ return ReadSaveStateRegisterByIndex (CpuInde= x, GetRegisterIndex (Register), Width, Buffer);
+}
+
+/**+ Writes an SMM Save State register on the target processor. If this fun= ction
+ returns EFI_UNSUPPORTED, then the caller is responsible for wr= iting 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 wr= ite.
+ @param[in] Width The number of bytes to write to the CPU save s= tate.
+ @param[in] Buffer Upon entry, this holds the new CPU register = value.
+
+ @retval EFI_SUCCESS The register was written to Save S= tate.
+ @retval EFI_INVALID_PARAMTER Buffer is NULL.
+ @retval EF= I_UNSUPPORTED This function does not support writing Register.
+**/+EFI_STATUS
+EFIAPI
+InternalSmmCpuFeaturesWriteSaveStateRegis= ter (
+ IN UINTN CpuIndex,
+ IN EFI_SMM_SAVE_STATE_REGISTER Regis= ter,
+ IN UINTN Width,
+ IN CONST VOID *Buffer
+ )
+{+ UINTN RegisterIndex;
+ AMD_SMRAM_SAVE_STATE_MAP *CpuSaveState;+
+ //
+ // Writes to EFI_SMM_SAVE_STATE_REGISTER_LMA are ign= ored
+ //
+ if (Register =3D=3D EFI_SMM_SAVE_STATE_REGISTER_LMA) = {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Writes to = EFI_SMM_SAVE_STATE_REGISTER_IO are not supported
+ //
+ if (Regis= ter =3D=3D EFI_SMM_SAVE_STATE_REGISTER_IO) {
+ return EFI_NOT_FOUND;+ }
+
+ //
+ // Convert Register to a register lookup ta= ble index
+ //
+ RegisterIndex =3D GetRegisterIndex (Register);+ if (RegisterIndex =3D=3D 0) {
+ return EFI_NOT_FOUND;
+ }+
+ CpuSaveState =3D gSmst->CpuSaveState[CpuIndex];
+
+ //
+ // Do not write non-writable SaveState, because it will cause = exception.
+ //
+ if (!mSmmCpuWidthOffset[RegisterIndex].Writeabl= e) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Che= ck CPU mode
+ //
+ if (mSmmSaveStateRegisterLma =3D=3D EFI_SMM_SA= VE_STATE_REGISTER_LMA_32BIT) {
+ //
+ // If 32-bit mode width is = zero, then the specified register can not be accessed
+ //
+ if (= mSmmCpuWidthOffset[RegisterIndex].Width32 =3D=3D 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 > mSmmCpuWidthOffset[RegisterIndex].Width32) {
+ re= turn EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Write SMM S= tate register
+ //
+ ASSERT (CpuSaveState !=3D NULL);
+ Copy= Mem ((UINT8 *)CpuSaveState + mSmmCpuWidthOffset[RegisterIndex].Offset32, Bu= ffer, Width);
+ } else {
+ //
+ // If 64-bit mode width is z= ero, then the specified register can not be accessed
+ //
+ if (m= SmmCpuWidthOffset[RegisterIndex].Width64 =3D=3D 0) {
+ return EFI_NOT_= FOUND;
+ }
+
+ //
+ // If Width is bigger than the 64-b= it mode width, then the specified register can not be accessed
+ //+ if (Width > mSmmCpuWidthOffset[RegisterIndex].Width64) {
+ ret= urn EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Write lower = 32-bits of SMM State register
+ //
+ CopyMem ((UINT8 *)CpuSaveSta= te + mSmmCpuWidthOffset[RegisterIndex].Offset64Lo, Buffer, MIN (4, Width));=
+ if (Width >=3D 4) {
+ //
+ // Write upper 32-bits of S= MM State register
+ //
+ CopyMem ((UINT8 *)CpuSaveState + mSmmCpu= WidthOffset[RegisterIndex].Offset64Hi, (UINT8 *)Buffer + 4, Width - 4);
+ }
+ }
+
+ return EFI_SUCCESS;
+}
--
2.25= .1
--deqQsT29TNeltRygQVqk--