From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from NAM10-BN7-obe.outbound.protection.outlook.com (NAM10-BN7-obe.outbound.protection.outlook.com [40.107.92.66]) by mx.groups.io with SMTP id smtpd.web11.47423.1670333038083689095 for ; Tue, 06 Dec 2022 05:23:58 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@amd.com header.s=selector1 header.b=1t8EyJ4c; spf=permerror, err=parse error for token &{10 18 %{i}._ip.%{h}._ehlo.%{d}._spf.vali.email}: invalid domain name (domain: amd.com, ip: 40.107.92.66, mailfrom: abdullateef.attar@amd.com) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=OSAImmxnAWdC/K247ZzOfZSNs2KW3Z2BRm2JVElDherAdIPE2Bon0KqQBXA+nRfma+tfD2H3pNYNJGiIgVTkiMxygmeOCDykiTfC3HxPewioJ6qvFJ47KoY5wABzXuQDrPDIEai6CcYqew42px369PcY6eRXNAu7MvX+bkVdrq6x9HiA5EUs2VZXYbrIPKbTaLfkITP0TZEDUwqTsLii5zlHQ/hJckWy0Cheec4RVbaZMRpMJKxjb2mgCkQApPJ0w+1vDmFodYLCWXq7TLedG5sHgThHaCvzQU/MVGLqkLhXiNGwQc1+J2rprmdH8VCfKp1VbhzlZEJXe6H7r+vu3w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=2fXeyuPxkxQfKobfEol0kGvQW/SiO1v+0MAHnXXEkiE=; b=EuXrkyLVqivRjfMUB1VaxhMZ+yPlFetqaqYmDhYFY7/x8bv3ip29Y1C3rpsqdU87NYUUJg9Uf3C713AKghCtCNgmhD0kBheFKXe+zxJVQNJ+5G6QYbt2hDmP5lvoIoXMt+ejJwmPu99X5+tDznunrGWNBLSNXMIFPsjnW4NvUv/1xReP/HorCmoKjqGi8r/bnMX2lM6RhtkkA/74tZyD1Z93e4Sp+QKZVPUooU33uPGU1TcgfnBb551gbZtv+5La0QkfaEANqmVhahYcAhpt1jpwdYLa+fe4IoNlvaC3VWdtnXji7T2PXHMTKi7sS003hVhAjJnt8EtudaerXdQ5Ug== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 165.204.84.17) smtp.rcpttodomain=edk2.groups.io smtp.mailfrom=amd.com; dmarc=pass (p=quarantine sp=quarantine pct=100) action=none header.from=amd.com; dkim=none (message not signed); arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amd.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=2fXeyuPxkxQfKobfEol0kGvQW/SiO1v+0MAHnXXEkiE=; b=1t8EyJ4ci0cQxEkPK8othWH370bSfPes5Rtv/AaRk/zZ2q5sHq4WIrrzSXv1UEk54S6S26VJ0Bq5Al/IOBUKymBBfY+URWtScl44SkWi2j8mYxJSHLGNcFTTKXcnfvsp7LjRNxwpOa5kuuhs/oqYHAAAfP45QnQlr3O0DsG0DzI= Received: from BN0PR02CA0003.namprd02.prod.outlook.com (2603:10b6:408:e4::8) by DM6PR12MB4353.namprd12.prod.outlook.com (2603:10b6:5:2a6::12) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5880.14; Tue, 6 Dec 2022 13:23:55 +0000 Received: from BN8NAM11FT111.eop-nam11.prod.protection.outlook.com (2603:10b6:408:e4:cafe::ae) by BN0PR02CA0003.outlook.office365.com (2603:10b6:408:e4::8) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5880.14 via Frontend Transport; Tue, 6 Dec 2022 13:23:55 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 165.204.84.17) smtp.mailfrom=amd.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=amd.com; Received-SPF: Pass (protection.outlook.com: domain of amd.com designates 165.204.84.17 as permitted sender) receiver=protection.outlook.com; client-ip=165.204.84.17; helo=SATLEXMB04.amd.com; pr=C Received: from SATLEXMB04.amd.com (165.204.84.17) by BN8NAM11FT111.mail.protection.outlook.com (10.13.177.54) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.5901.14 via Frontend Transport; Tue, 6 Dec 2022 13:23:54 +0000 Received: from SATLEXMB08.amd.com (10.181.40.132) by SATLEXMB04.amd.com (10.181.40.145) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2375.34; Tue, 6 Dec 2022 07:23:54 -0600 Received: from SATLEXMB03.amd.com (10.181.40.144) by SATLEXMB08.amd.com (10.181.40.132) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2375.34; Tue, 6 Dec 2022 05:23:53 -0800 Received: from BLR-LAB-SFW01.amd.com (10.180.168.240) by SATLEXMB03.amd.com (10.181.40.144) with Microsoft SMTP Server id 15.1.2375.34 via Frontend Transport; Tue, 6 Dec 2022 07:23:51 -0600 From: "Abdul Lateef Attar" To: CC: Abdul Lateef Attar , Paul Grimes , Garrett Kirkendall , Abner Chang , Eric Dong , Ray Ni , Rahul Kumar Subject: [PATCH v1 4/5] UefiCpuPkg: Implements SmmCpuFeaturesLib for AMD Family Date: Tue, 6 Dec 2022 18:53:17 +0530 Message-ID: <79f976894da303d126fca5f6ace608391082d288.1670332633.git.abdattar@amd.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: References: MIME-Version: 1.0 Return-Path: AbdulLateef.Attar@amd.com X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: BN8NAM11FT111:EE_|DM6PR12MB4353:EE_ X-MS-Office365-Filtering-Correlation-Id: 66d3c090-03de-41fe-d436-08dad78d1f9a X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: dPFH3eR0JxrkEGwguScqmdsDDS7lyDjl9AyP6c8bD84mO7zJLaWbNFm0oS4W+ADnengdjKRoXdE1Ft7qVsFQT1JTZ5hKB5aAwr2sX7/kNkc+Y1m5QflrSeJAwTRH5/D6NZB8LaoBorlAJJ2+HwNqC4E6iPEqe+iusEM/JPSnIlG0TxGyqNv0GlxX4bfjtmHyUX+Um91bsBPtcBZ28iHIsQ47V971F2AAbI9Fp1SbGUstktpp2Ttszuk+jG2lOujhFsYsbPc0gQce1naYUlsnx1Sij5DOkJhB+U0lBnGip/WoX8H8LpUdnZPlniQ/QBkqkTC5AZlykuqcETsEWaxthkVuknxyvlXyYRRCjgDtGST2ZjOuqjHXEEWixOS5D0n0veK5urrhV5ycYnJ93uHNrOOEHGSNeeKH2uA3ruRGuC0eJl8W2eU4zlrHKd4jocyH6SMINSaaN60Z7xWXyyB7wLmLKFvGCEQXB3ufViadqz44oAH/ybLiLcZhzk8u0PsyD7G3CWlZfE/UPJ3q9jb8W6e1rVcLNpOZk+Tdxw4/Kr0cyIKCl/1YVR2zvV2muX+OqXRLMYnRmRWS5olrMV/Kp7m+3VEMKtC77/y7OIB0plRsAq50UgFp3lRo0f6tqhHPao2oc4R4Si8lsx1TVxFaNrv1j5aIcMtsTqTZ2JbcAsECvHXYwmrCY2knQxK2TxResd/wrQGkjm77yiD3J4inQWX9W+ic3Rq9nycdKCFnqxi0RTNjRHaigFHm4M9Jr14Mz8LUTNP29mOvPcIMCuYmIw== X-Forefront-Antispam-Report: CIP:165.204.84.17;CTRY:US;LANG:en;SCL:1;SRV:;IPV:CAL;SFV:NSPM;H:SATLEXMB04.amd.com;PTR:InfoDomainNonexistent;CAT:NONE;SFS:(13230022)(4636009)(136003)(39860400002)(346002)(396003)(376002)(451199015)(40470700004)(46966006)(36840700001)(36756003)(36860700001)(70206006)(82740400003)(4326008)(8676002)(186003)(70586007)(2616005)(336012)(426003)(83380400001)(40460700003)(26005)(7696005)(6666004)(478600001)(54906003)(6916009)(966005)(316002)(82310400005)(47076005)(2906002)(40480700001)(356005)(41300700001)(81166007)(8936002)(30864003)(5660300002)(36900700001);DIR:OUT;SFP:1101; X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 06 Dec 2022 13:23:54.6478 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 66d3c090-03de-41fe-d436-08dad78d1f9a X-MS-Exchange-CrossTenant-Id: 3dd8961f-e488-4e60-8e11-a82d994e183d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=3dd8961f-e488-4e60-8e11-a82d994e183d;Ip=[165.204.84.17];Helo=[SATLEXMB04.amd.com] X-MS-Exchange-CrossTenant-AuthSource: BN8NAM11FT111.eop-nam11.prod.protection.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: DM6PR12MB4353 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain From: Abdul Lateef Attar BZ: https://bugzilla.tianocore.org/show_bug.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 corrects the IP once control returns from SMM. 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 diff --git a/UefiCpuPkg/Library/SmmCpuFeaturesLib/AmdSmmCpuFeaturesLib.inf = 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=0D SmmCpuFeaturesLibCommon.c=0D Amd/SmmCpuFeaturesLib.c=0D + Amd/SmramSaveState.c=0D + Amd/SmramSaveState.h=0D =0D [Packages]=0D MdePkg/MdePkg.dec=0D diff --git a/UefiCpuPkg/Library/SmmCpuFeaturesLib/Amd/SmramSaveState.h b/Ue= fiCpuPkg/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=0D +SMRAM Save State Map header file.=0D +=0D +Copyright (c) 2010 - 2019, Intel Corporation. All rights reserved.
=0D +Copyright (C) 2022 Advanced Micro Devices, Inc. All rights reserved.
=0D +SPDX-License-Identifier: BSD-2-Clause-Patent=0D +=0D +**/=0D +=0D +#ifndef SMRAM_SAVESTATE_H_=0D +#define SMRAM_SAVESTATE_H_=0D +=0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +=0D +// EFER register LMA bit=0D +#define LMA BIT10=0D +=0D +// Machine Specific Registers (MSRs)=0D +#define SMMADDR_ADDRESS 0xC0010112ul=0D +#define SMMMASK_ADDRESS 0xC0010113ul=0D +#define EFER_ADDRESS 0XC0000080ul=0D +=0D +// Macro used to simplify the lookup table entries of type CPU_SMM_SAVE_ST= ATE_LOOKUP_ENTRY=0D +#define SMM_CPU_OFFSET(Field) OFFSET_OF (AMD_SMRAM_SAVE_STATE_MAP, Field)= =0D +=0D +// Macro used to simplify the lookup table entries of type CPU_SMM_SAVE_ST= ATE_REGISTER_RANGE=0D +#define SMM_REGISTER_RANGE(Start, End) { Start, End, End - Start + 1 }=0D +=0D +// Structure used to describe a range of registers=0D +typedef struct {=0D + EFI_SMM_SAVE_STATE_REGISTER Start;=0D + EFI_SMM_SAVE_STATE_REGISTER End;=0D + UINTN Length;=0D +} CPU_SMM_SAVE_STATE_REGISTER_RANGE;=0D +=0D +// Structure used to build a lookup table to retrieve the widths and offse= ts=0D +// associated with each supported EFI_SMM_SAVE_STATE_REGISTER value=0D +=0D +#define SMM_SAVE_STATE_REGISTER_SMMREVID_INDEX 1=0D +#define SMM_SAVE_STATE_REGISTER_MAX_INDEX 2=0D +=0D +typedef struct {=0D + UINT8 Width32;=0D + UINT8 Width64;=0D + UINT16 Offset32;=0D + UINT16 Offset64Lo;=0D + UINT16 Offset64Hi;=0D + BOOLEAN Writeable;=0D +} CPU_SMM_SAVE_STATE_LOOKUP_ENTRY;=0D +=0D +/**=0D + Read an SMM Save State register on the target processor. If this functi= on=0D + returns EFI_UNSUPPORTED, then the caller is responsible for reading the= =0D + SMM Save Sate register.=0D +=0D + @param[in] CpuIndex The index of the CPU to read the SMM Save State. = The=0D + value must be between 0 and the NumberOfCpus field= in=0D + the System Management System Table (SMST).=0D + @param[in] Register The SMM Save State register to read.=0D + @param[in] Width The number of bytes to read from the CPU save stat= e.=0D + @param[out] Buffer Upon return, this holds the CPU register value rea= d=0D + from the save state.=0D +=0D + @retval EFI_SUCCESS The register was read from Save State.=0D + @retval EFI_INVALID_PARAMTER Buffer is NULL.=0D + @retval EFI_UNSUPPORTED This function does not support reading Reg= ister.=0D +=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +InternalSmmCpuFeaturesReadSaveStateRegister (=0D + IN UINTN CpuIndex,=0D + IN EFI_SMM_SAVE_STATE_REGISTER Register,=0D + IN UINTN Width,=0D + OUT VOID *Buffer=0D + );=0D +=0D +/**=0D + Writes an SMM Save State register on the target processor. If this func= tion=0D + returns EFI_UNSUPPORTED, then the caller is responsible for writing the= =0D + SMM Save Sate register.=0D +=0D + @param[in] CpuIndex The index of the CPU to write the SMM Save State. = The=0D + value must be between 0 and the NumberOfCpus field = in=0D + the System Management System Table (SMST).=0D + @param[in] Register The SMM Save State register to write.=0D + @param[in] Width The number of bytes to write to the CPU save state.= =0D + @param[in] Buffer Upon entry, this holds the new CPU register value.= =0D +=0D + @retval EFI_SUCCESS The register was written to Save State.=0D + @retval EFI_INVALID_PARAMTER Buffer is NULL.=0D + @retval EFI_UNSUPPORTED This function does not support writing Reg= ister.=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +InternalSmmCpuFeaturesWriteSaveStateRegister (=0D + IN UINTN CpuIndex,=0D + IN EFI_SMM_SAVE_STATE_REGISTER Register,=0D + IN UINTN Width,=0D + IN CONST VOID *Buffer=0D + );=0D +=0D +#endif=0D 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 =0D **/=0D =0D -#include =0D -#include =0D +#include "SmramSaveState.h"=0D +=0D +// The mode of the CPU at the time an SMI occurs=0D +extern UINT8 mSmmSaveStateRegisterLma;=0D =0D /**=0D Read an SMM Save State register on the target processor. If this functi= on=0D @@ -39,7 +41,7 @@ SmmCpuFeaturesReadSaveStateRegister ( OUT VOID *Buffer=0D )=0D {=0D - return EFI_SUCCESS;=0D + return InternalSmmCpuFeaturesReadSaveStateRegister (CpuIndex, Register, = Width, Buffer);=0D }=0D =0D /**=0D @@ -67,7 +69,7 @@ SmmCpuFeaturesWriteSaveStateRegister ( IN CONST VOID *Buffer=0D )=0D {=0D - return EFI_SUCCESS;=0D + return InternalSmmCpuFeaturesWriteSaveStateRegister (CpuIndex, Register,= Width, Buffer);=0D }=0D =0D /**=0D @@ -82,6 +84,13 @@ CpuFeaturesLibInitialization ( VOID=0D )=0D {=0D + UINT32 LMAValue;=0D +=0D + LMAValue =3D (UINT32)AsmReadMsr64 (EFER_ADDRESS) & LMA;= =0D + mSmmSaveStateRegisterLma =3D EFI_SMM_SAVE_STATE_REGISTER_LMA_32BIT;=0D + if (LMAValue) {=0D + mSmmSaveStateRegisterLma =3D EFI_SMM_SAVE_STATE_REGISTER_LMA_64BIT;=0D + }=0D }=0D =0D /**=0D @@ -117,6 +126,52 @@ SmmCpuFeaturesInitializeProcessor ( IN CPU_HOT_PLUG_DATA *CpuHotPlugData=0D )=0D {=0D + AMD_SMRAM_SAVE_STATE_MAP *CpuState;=0D + UINT32 LMAValue;=0D +=0D + //=0D + // Configure SMBASE.=0D + //=0D + CpuState =3D (AMD_SMRAM_SAVE_STATE_MAP *)(UINTN)(SMM_DEFAULT= _SMBASE + SMRAM_SAVE_STATE_MAP_OFFSET);=0D + CpuState->x64.SMBASE =3D (UINT32)CpuHotPlugData->SmBase[CpuIndex];=0D +=0D + // Re-initialize the value of mSmmSaveStateRegisterLma flag which might = have been changed in PiCpuSmmDxeSmm Driver=0D + // Entry point, to make sure correct value on AMD platform is assigned t= o be used by SmmCpuFeaturesLib.=0D + LMAValue =3D (UINT32)AsmReadMsr64 (EFER_ADDRESS) & LMA;= =0D + mSmmSaveStateRegisterLma =3D EFI_SMM_SAVE_STATE_REGISTER_LMA_32BIT;=0D + if (LMAValue) {=0D + mSmmSaveStateRegisterLma =3D EFI_SMM_SAVE_STATE_REGISTER_LMA_64BIT;=0D + }=0D +=0D + //=0D + // If SMRR is supported, then program SMRR base/mask MSRs.=0D + // The EFI_MSR_SMRR_PHYS_MASK_VALID bit is not set until the first norma= l SMI.=0D + // The code that initializes SMM environment is running in normal mode=0D + // from SMRAM region. If SMRR is enabled here, then the SMRAM region=0D + // is protected and the normal mode code execution will fail.=0D + //=0D + if (FeaturePcdGet (PcdSmrrEnable)) {=0D + //=0D + // SMRR size cannot be less than 4-KBytes=0D + // SMRR size must be of length 2^n=0D + // SMRR base alignment cannot be less than SMRR length=0D + //=0D + if ((CpuHotPlugData->SmrrSize < SIZE_4KB) ||=0D + (CpuHotPlugData->SmrrSize !=3D GetPowerOfTwo32 (CpuHotPlugData->Sm= rrSize)) ||=0D + ((CpuHotPlugData->SmrrBase & ~(CpuHotPlugData->SmrrSize - 1)) !=3D= CpuHotPlugData->SmrrBase))=0D + {=0D + //=0D + // Print message and halt if CPU is Monarch=0D + //=0D + if (IsMonarch) {=0D + DEBUG ((DEBUG_ERROR, "SMM Base/Size does not meet alignment/size r= equirement!\n"));=0D + CpuDeadLoop ();=0D + }=0D + } else {=0D + AsmWriteMsr64 (SMMADDR_ADDRESS, CpuHotPlugData->SmrrBase);=0D + AsmWriteMsr64 (SMMMASK_ADDRESS, ((~(UINT64)(CpuHotPlugData->SmrrSize= - 1)) | 0x6600));=0D + }=0D + }=0D }=0D =0D /**=0D @@ -159,7 +214,39 @@ SmmCpuFeaturesHookReturnFromSmm ( IN UINT64 NewInstructionPointer=0D )=0D {=0D - return 0;=0D + UINT64 OriginalInstructionPointer;=0D + AMD_SMRAM_SAVE_STATE_MAP *AmdCpuState;=0D +=0D + AmdCpuState =3D (AMD_SMRAM_SAVE_STATE_MAP *)CpuState;=0D +=0D + if (mSmmSaveStateRegisterLma =3D=3D EFI_SMM_SAVE_STATE_REGISTER_LMA_32BI= T) {=0D + OriginalInstructionPointer =3D (UINT64)AmdCpuState->x86._EIP;=0D + AmdCpuState->x86._EIP =3D (UINT32)NewInstructionPointer;=0D + //=0D + // Clear the auto HALT restart flag so the RSM instruction returns=0D + // program control to the instruction following the HLT instruction.=0D + //=0D + if ((AmdCpuState->x86.AutoHALTRestart & BIT0) !=3D 0) {=0D + AmdCpuState->x86.AutoHALTRestart &=3D ~BIT0;=0D + }=0D + } else {=0D + OriginalInstructionPointer =3D AmdCpuState->x64._RIP;=0D + if ((AmdCpuState->x64.EFER & LMA) =3D=3D 0) {=0D + AmdCpuState->x64._RIP =3D (UINT32)NewInstructionPointer32;=0D + } else {=0D + AmdCpuState->x64._RIP =3D (UINT32)NewInstructionPointer;=0D + }=0D +=0D + //=0D + // Clear the auto HALT restart flag so the RSM instruction returns=0D + // program control to the instruction following the HLT instruction.=0D + //=0D + if ((AmdCpuState->x64.AutoHALTRestart & BIT0) !=3D 0) {=0D + AmdCpuState->x64.AutoHALTRestart &=3D ~BIT0;=0D + }=0D + }=0D +=0D + return OriginalInstructionPointer;=0D }=0D =0D /**=0D diff --git a/UefiCpuPkg/Library/SmmCpuFeaturesLib/Amd/SmramSaveState.c b/Ue= fiCpuPkg/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=0D +Provides services to access SMRAM Save State Map=0D +=0D +Copyright (c) 2010 - 2019, Intel Corporation. All rights reserved.
=0D +Copyright (C) 2022 Advanced Micro Devices, Inc. All rights reserved.
=0D +SPDX-License-Identifier: BSD-2-Clause-Patent=0D +=0D +**/=0D +=0D +#include "SmramSaveState.h"=0D +=0D +// The mode of the CPU at the time an SMI occurs=0D +extern UINT8 mSmmSaveStateRegisterLma;=0D +=0D +// Table used by GetRegisterIndex() to convert an EFI_SMM_SAVE_STATE_REGIS= TER=0D +// value to an index into a table of type CPU_SMM_SAVE_STATE_LOOKUP_ENTRY= =0D +static CONST CPU_SMM_SAVE_STATE_REGISTER_RANGE mSmmCpuRegisterRanges[] = =3D {=0D + SMM_REGISTER_RANGE (EFI_SMM_SAVE_STATE_REGISTER_GDTBASE, EFI_SMM_SAVE_ST= ATE_REGISTER_LDTINFO),=0D + SMM_REGISTER_RANGE (EFI_SMM_SAVE_STATE_REGISTER_ES, EFI_SMM_SAVE_ST= ATE_REGISTER_RIP),=0D + SMM_REGISTER_RANGE (EFI_SMM_SAVE_STATE_REGISTER_RFLAGS, EFI_SMM_SAVE_ST= ATE_REGISTER_CR4),=0D + { (EFI_SMM_SAVE_STATE_REGISTER)0, (EFI_SMM_SAVE_S= TATE_REGISTER)0, 0}=0D +};=0D +=0D +// Lookup table used to retrieve the widths and offsets associated with ea= ch=0D +// supported EFI_SMM_SAVE_STATE_REGISTER value=0D +static CONST CPU_SMM_SAVE_STATE_LOOKUP_ENTRY mSmmCpuWidthOffset[] =3D {=0D + { 0, 0, 0, 0, = FALSE }, // Reserved=0D +=0D + //=0D + // Internally defined CPU Save State Registers. Not defined in PI SMM CP= U Protocol.=0D + //=0D + { 4, 4, SMM_CPU_OFFSET (x86.SMMRevId), SMM_CPU_OFFSET (x64.SMMRevId), = 0, FALSE}, // SMM_SAVE_STATE_R= EGISTER_SMMREVID_INDEX =3D 1=0D +=0D + //=0D + // CPU Save State registers defined in PI SMM CPU Protocol.=0D + //=0D + { 4, 8, SMM_CPU_OFFSET (x86.GDTBase), SMM_CPU_OFFSET (x64._GDTRBaseLoDw= ord), SMM_CPU_OFFSET (x64._GDTRBaseHiDword), FALSE}, // EFI_SMM_SAVE_ST= ATE_REGISTER_GDTBASE =3D 4=0D + { 0, 8, 0, SMM_CPU_OFFSET (x64._IDTRBaseLoDw= ord), SMM_CPU_OFFSET (x64._IDTRBaseLoDword), FALSE}, // EFI_SMM_SAVE_ST= ATE_REGISTER_IDTBASE =3D 5=0D + { 0, 8, 0, SMM_CPU_OFFSET (x64._LDTRBaseLoDw= ord), SMM_CPU_OFFSET (x64._LDTRBaseLoDword), FALSE}, // EFI_SMM_SAVE_ST= ATE_REGISTER_LDTBASE =3D 6=0D + { 0, 2, 0, SMM_CPU_OFFSET (x64._GDTRLimit), = 0, FALSE}, // EFI_SMM_SAVE_ST= ATE_REGISTER_GDTLIMIT =3D 7=0D + { 0, 2, 0, SMM_CPU_OFFSET (x64._IDTRLimit), = 0, FALSE}, // EFI_SMM_SAVE_ST= ATE_REGISTER_IDTLIMIT =3D 8=0D + { 0, 4, 0, SMM_CPU_OFFSET (x64._LDTRLimit), = 0, FALSE}, // EFI_SMM_SAVE_ST= ATE_REGISTER_LDTLIMIT =3D 9=0D + { 0, 0, 0, 0, = 0, FALSE}, // EFI_SMM_SAVE_ST= ATE_REGISTER_LDTINFO =3D 10=0D + { 4, 2, SMM_CPU_OFFSET (x86._ES), SMM_CPU_OFFSET (x64._ES), = 0, FALSE}, // EFI_SMM_SAVE_ST= ATE_REGISTER_ES =3D 20=0D + { 4, 2, SMM_CPU_OFFSET (x86._CS), SMM_CPU_OFFSET (x64._CS), = 0, FALSE}, // EFI_SMM_SAVE_ST= ATE_REGISTER_CS =3D 21=0D + { 4, 2, SMM_CPU_OFFSET (x86._SS), SMM_CPU_OFFSET (x64._SS), = 0, FALSE}, // EFI_SMM_SAVE_ST= ATE_REGISTER_SS =3D 22=0D + { 4, 2, SMM_CPU_OFFSET (x86._DS), SMM_CPU_OFFSET (x64._DS), = 0, FALSE}, // EFI_SMM_SAVE_ST= ATE_REGISTER_DS =3D 23=0D + { 4, 2, SMM_CPU_OFFSET (x86._FS), SMM_CPU_OFFSET (x64._FS), = 0, FALSE}, // EFI_SMM_SAVE_ST= ATE_REGISTER_FS =3D 24=0D + { 4, 2, SMM_CPU_OFFSET (x86._GS), SMM_CPU_OFFSET (x64._GS), = 0, FALSE}, // EFI_SMM_SAVE_ST= ATE_REGISTER_GS =3D 25=0D + { 0, 2, 0, SMM_CPU_OFFSET (x64._LDTR), = 0, FALSE}, // EFI_SMM_SAVE_ST= ATE_REGISTER_LDTR_SEL =3D 26=0D + { 0, 2, 0, SMM_CPU_OFFSET (x64._TR), = 0, FALSE}, // EFI_SMM_SAVE_ST= ATE_REGISTER_TR_SEL =3D 27=0D + { 4, 8, SMM_CPU_OFFSET (x86._DR7), SMM_CPU_OFFSET (x64._DR7), = SMM_CPU_OFFSET (x64._DR7) + 4, FALSE}, // EFI_SMM_SAVE_ST= ATE_REGISTER_DR7 =3D 28=0D + { 4, 8, SMM_CPU_OFFSET (x86._DR6), SMM_CPU_OFFSET (x64._DR6), = SMM_CPU_OFFSET (x64._DR6) + 4, FALSE}, // EFI_SMM_SAVE_ST= ATE_REGISTER_DR6 =3D 29=0D + { 0, 8, 0, SMM_CPU_OFFSET (x64._R8), = SMM_CPU_OFFSET (x64._R8) + 4, TRUE}, // EFI_SMM_SAVE_ST= ATE_REGISTER_R8 =3D 30=0D + { 0, 8, 0, SMM_CPU_OFFSET (x64._R9), = SMM_CPU_OFFSET (x64._R9) + 4, TRUE}, // EFI_SMM_SAVE_ST= ATE_REGISTER_R9 =3D 31=0D + { 0, 8, 0, SMM_CPU_OFFSET (x64._R10), = SMM_CPU_OFFSET (x64._R10) + 4, TRUE}, // EFI_SMM_SAVE_ST= ATE_REGISTER_R10 =3D 32=0D + { 0, 8, 0, SMM_CPU_OFFSET (x64._R11), = SMM_CPU_OFFSET (x64._R11) + 4, TRUE}, // EFI_SMM_SAVE_ST= ATE_REGISTER_R11 =3D 33=0D + { 0, 8, 0, SMM_CPU_OFFSET (x64._R12), = SMM_CPU_OFFSET (x64._R12) + 4, TRUE}, // EFI_SMM_SAVE_ST= ATE_REGISTER_R12 =3D 34=0D + { 0, 8, 0, SMM_CPU_OFFSET (x64._R13), = SMM_CPU_OFFSET (x64._R13) + 4, TRUE}, // EFI_SMM_SAVE_ST= ATE_REGISTER_R13 =3D 35=0D + { 0, 8, 0, SMM_CPU_OFFSET (x64._R14), = SMM_CPU_OFFSET (x64._R14) + 4, TRUE}, // EFI_SMM_SAVE_ST= ATE_REGISTER_R14 =3D 36=0D + { 0, 8, 0, SMM_CPU_OFFSET (x64._R15), = SMM_CPU_OFFSET (x64._R15) + 4, TRUE}, // EFI_SMM_SAVE_ST= ATE_REGISTER_R15 =3D 37=0D + { 4, 8, SMM_CPU_OFFSET (x86._EAX), SMM_CPU_OFFSET (x64._RAX), = SMM_CPU_OFFSET (x64._RAX) + 4, TRUE}, // EFI_SMM_SAVE_ST= ATE_REGISTER_RAX =3D 38=0D + { 4, 8, SMM_CPU_OFFSET (x86._EBX), SMM_CPU_OFFSET (x64._RBX), = SMM_CPU_OFFSET (x64._RBX) + 4, TRUE}, // EFI_SMM_SAVE_ST= ATE_REGISTER_RBX =3D 39=0D + { 4, 8, SMM_CPU_OFFSET (x86._ECX), SMM_CPU_OFFSET (x64._RCX), = SMM_CPU_OFFSET (x64._RCX) + 4, TRUE}, // EFI_SMM_SAVE_ST= ATE_REGISTER_RBX =3D 39=0D + { 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=0D + { 4, 8, SMM_CPU_OFFSET (x86._ESP), SMM_CPU_OFFSET (x64._RSP), = SMM_CPU_OFFSET (x64._RSP) + 4, TRUE}, // EFI_SMM_SAVE_ST= ATE_REGISTER_RSP =3D 42=0D + { 4, 8, SMM_CPU_OFFSET (x86._EBP), SMM_CPU_OFFSET (x64._RBP), = SMM_CPU_OFFSET (x64._RBP) + 4, TRUE}, // EFI_SMM_SAVE_ST= ATE_REGISTER_RBP =3D 43=0D + { 4, 8, SMM_CPU_OFFSET (x86._ESI), SMM_CPU_OFFSET (x64._RSI), = SMM_CPU_OFFSET (x64._RSI) + 4, TRUE}, // EFI_SMM_SAVE_ST= ATE_REGISTER_RSI =3D 44=0D + { 4, 8, SMM_CPU_OFFSET (x86._EDI), SMM_CPU_OFFSET (x64._RDI), = SMM_CPU_OFFSET (x64._RDI) + 4, TRUE}, // EFI_SMM_SAVE_ST= ATE_REGISTER_RDI =3D 45=0D + { 4, 8, SMM_CPU_OFFSET (x86._EIP), SMM_CPU_OFFSET (x64._RIP), = SMM_CPU_OFFSET (x64._RIP) + 4, TRUE}, // EFI_SMM_SAVE_ST= ATE_REGISTER_RIP =3D 46=0D +=0D + { 4, 8, SMM_CPU_OFFSET (x86._EFLAGS), SMM_CPU_OFFSET (x64._RFLAGS), = SMM_CPU_OFFSET (x64._RFLAGS) + 4, TRUE}, // EFI_SMM_SAVE_ST= ATE_REGISTER_RFLAGS =3D 51=0D + { 4, 8, SMM_CPU_OFFSET (x86._CR0), SMM_CPU_OFFSET (x64._CR0), = SMM_CPU_OFFSET (x64._CR0) + 4, FALSE}, // EFI_SMM_SAVE_ST= ATE_REGISTER_CR0 =3D 52=0D + { 4, 8, SMM_CPU_OFFSET (x86._CR3), SMM_CPU_OFFSET (x64._CR3), = SMM_CPU_OFFSET (x64._CR3) + 4, FALSE}, // EFI_SMM_SAVE_ST= ATE_REGISTER_CR3 =3D 53=0D + { 0, 8, 0, SMM_CPU_OFFSET (x64._CR4), = SMM_CPU_OFFSET (x64._CR4) + 4, FALSE}, // EFI_SMM_SAVE_ST= ATE_REGISTER_CR4 =3D 54=0D + { 0, 0, 0, 0, = 0 }=0D +};=0D +=0D +/**=0D + Read information from the CPU save state.=0D +=0D + @param Register Specifies the CPU register to read form the save state= .=0D +=0D + @retval 0 Register is not valid=0D + @retval >0 Index into mSmmCpuWidthOffset[] associated with Register=0D +=0D +**/=0D +STATIC=0D +UINTN=0D +EFIAPI=0D +GetRegisterIndex (=0D + IN EFI_SMM_SAVE_STATE_REGISTER Register=0D + )=0D +{=0D + UINTN Index;=0D + UINTN Offset;=0D +=0D + for (Index =3D 0, Offset =3D SMM_SAVE_STATE_REGISTER_MAX_INDEX; mSmmCpuR= egisterRanges[Index].Length !=3D 0; Index++) {=0D + if ((Register >=3D mSmmCpuRegisterRanges[Index].Start) && (Register <= =3D mSmmCpuRegisterRanges[Index].End)) {=0D + return Register - mSmmCpuRegisterRanges[Index].Start + Offset;=0D + }=0D +=0D + Offset +=3D mSmmCpuRegisterRanges[Index].Length;=0D + }=0D +=0D + return 0;=0D +}=0D +=0D +/**=0D + Read a CPU Save State register on the target processor.=0D +=0D + This function abstracts the differences that whether the CPU Save State = register is in the=0D + IA32 CPU Save State Map or X64 CPU Save State Map.=0D +=0D + This function supports reading a CPU Save State register in SMBase reloc= ation handler.=0D +=0D + @param[in] CpuIndex Specifies the zero-based index of the CPU sav= e state.=0D + @param[in] RegisterIndex Index into mSmmCpuWidthOffset[] look up table= .=0D + @param[in] Width The number of bytes to read from the CPU save= state.=0D + @param[out] Buffer Upon return, this holds the CPU register valu= e read from the save state.=0D +=0D + @retval EFI_SUCCESS The register was read from Save State.=0D + @retval EFI_NOT_FOUND The register is not defined for the Save S= tate of Processor.=0D + @retval EFI_INVALID_PARAMTER This or Buffer is NULL.=0D +=0D +**/=0D +STATIC=0D +EFI_STATUS=0D +EFIAPI=0D +ReadSaveStateRegisterByIndex (=0D + IN UINTN CpuIndex,=0D + IN UINTN RegisterIndex,=0D + IN UINTN Width,=0D + OUT VOID *Buffer=0D + )=0D +{=0D + AMD_SMRAM_SAVE_STATE_MAP *CpuSaveState;=0D +=0D + // UINT32 SmmRevId;=0D +=0D + if (RegisterIndex =3D=3D 0) {=0D + return EFI_NOT_FOUND;=0D + }=0D +=0D + CpuSaveState =3D gSmst->CpuSaveState[CpuIndex];=0D + // SmmRevId =3D CpuSaveState->x86.SMMRevId;=0D +=0D + if (mSmmSaveStateRegisterLma =3D=3D EFI_SMM_SAVE_STATE_REGISTER_LMA_32BI= T) {=0D + //=0D + // If 32-bit mode width is zero, then the specified register can not b= e accessed=0D + //=0D + if (mSmmCpuWidthOffset[RegisterIndex].Width32 =3D=3D 0) {=0D + return EFI_NOT_FOUND;=0D + }=0D +=0D + //=0D + // If Width is bigger than the 32-bit mode width, then the specified r= egister can not be accessed=0D + //=0D + if (Width > mSmmCpuWidthOffset[RegisterIndex].Width32) {=0D + return EFI_INVALID_PARAMETER;=0D + }=0D +=0D + //=0D + // Write return buffer=0D + //=0D + ASSERT (CpuSaveState !=3D NULL);=0D + CopyMem (Buffer, (UINT8 *)CpuSaveState + mSmmCpuWidthOffset[RegisterIn= dex].Offset32, Width);=0D + } else {=0D + //=0D + // If 64-bit mode width is zero, then the specified register can not b= e accessed=0D + //=0D + if (mSmmCpuWidthOffset[RegisterIndex].Width64 =3D=3D 0) {=0D + return EFI_NOT_FOUND;=0D + }=0D +=0D + //=0D + // If Width is bigger than the 64-bit mode width, then the specified r= egister can not be accessed=0D + //=0D + if (Width > mSmmCpuWidthOffset[RegisterIndex].Width64) {=0D + return EFI_INVALID_PARAMETER;=0D + }=0D +=0D + //=0D + // Write lower 32-bits of return buffer=0D + //=0D + CopyMem (Buffer, (UINT8 *)CpuSaveState + mSmmCpuWidthOffset[RegisterIn= dex].Offset64Lo, MIN (4, Width));=0D + if (Width >=3D 4) {=0D + //=0D + // Write upper 32-bits of return buffer=0D + //=0D + CopyMem ((UINT8 *)Buffer + 4, (UINT8 *)CpuSaveState + mSmmCpuWidthOf= fset[RegisterIndex].Offset64Hi, Width - 4);=0D + }=0D + }=0D +=0D + return EFI_SUCCESS;=0D +}=0D +=0D +/**=0D + Read an SMM Save State register on the target processor. If this functi= on=0D + returns EFI_UNSUPPORTED, then the caller is responsible for reading the= =0D + SMM Save Sate register.=0D +=0D + @param[in] CpuIndex The index of the CPU to read the SMM Save State. = The=0D + value must be between 0 and the NumberOfCpus field= in=0D + the System Management System Table (SMST).=0D + @param[in] Register The SMM Save State register to read.=0D + @param[in] Width The number of bytes to read from the CPU save stat= e.=0D + @param[out] Buffer Upon return, this holds the CPU register value rea= d=0D + from the save state.=0D +=0D + @retval EFI_SUCCESS The register was read from Save State.=0D + @retval EFI_INVALID_PARAMTER Buffer is NULL.=0D + @retval EFI_UNSUPPORTED This function does not support reading Reg= ister.=0D +=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +InternalSmmCpuFeaturesReadSaveStateRegister (=0D + IN UINTN CpuIndex,=0D + IN EFI_SMM_SAVE_STATE_REGISTER Register,=0D + IN UINTN Width,=0D + OUT VOID *Buffer=0D + )=0D +{=0D + UINT32 SmmRevId;=0D + EFI_SMM_SAVE_STATE_IO_INFO *IoInfo;=0D + AMD_SMRAM_SAVE_STATE_MAP *CpuSaveState;=0D + UINT8 DataWidth;=0D +=0D + // Read CPU State=0D + CpuSaveState =3D (AMD_SMRAM_SAVE_STATE_MAP *)gSmst->CpuSaveState[CpuInde= x];=0D +=0D + // Check for special EFI_SMM_SAVE_STATE_REGISTER_LMA=0D + if (Register =3D=3D EFI_SMM_SAVE_STATE_REGISTER_LMA) {=0D + // Only byte access is supported for this register=0D + if (Width !=3D 1) {=0D + return EFI_INVALID_PARAMETER;=0D + }=0D +=0D + *(UINT8 *)Buffer =3D mSmmSaveStateRegisterLma;=0D +=0D + return EFI_SUCCESS;=0D + }=0D +=0D + // Check for special EFI_SMM_SAVE_STATE_REGISTER_IO=0D +=0D + if (Register =3D=3D EFI_SMM_SAVE_STATE_REGISTER_IO) {=0D + //=0D + // Get SMM Revision ID=0D + //=0D + ReadSaveStateRegisterByIndex (CpuIndex, SMM_SAVE_STATE_REGISTER_SMMREV= ID_INDEX, sizeof (SmmRevId), &SmmRevId);=0D +=0D + //=0D + // See if the CPU supports the IOMisc register in the save state=0D + //=0D + if (SmmRevId < AMD_SMM_MIN_REV_ID_X64) {=0D + return EFI_NOT_FOUND;=0D + }=0D +=0D + // Check if IO Restart Dword [IO Trap] is valid or not using bit 1.=0D + if (!(CpuSaveState->x64.IO_DWord & 0x02u)) {=0D + return EFI_NOT_FOUND;=0D + }=0D +=0D + // Zero the IoInfo structure that will be returned in Buffer=0D + IoInfo =3D (EFI_SMM_SAVE_STATE_IO_INFO *)Buffer;=0D + ZeroMem (IoInfo, sizeof (EFI_SMM_SAVE_STATE_IO_INFO));=0D +=0D + IoInfo->IoPort =3D (UINT16)(CpuSaveState->x64.IO_DWord >> 16u);=0D +=0D + if (CpuSaveState->x64.IO_DWord & 0x10u) {=0D + IoInfo->IoWidth =3D EFI_SMM_SAVE_STATE_IO_WIDTH_UINT8;=0D + DataWidth =3D 0x01u;=0D + } else if (CpuSaveState->x64.IO_DWord & 0x20u) {=0D + IoInfo->IoWidth =3D EFI_SMM_SAVE_STATE_IO_WIDTH_UINT16;=0D + DataWidth =3D 0x02u;=0D + } else {=0D + IoInfo->IoWidth =3D EFI_SMM_SAVE_STATE_IO_WIDTH_UINT32;=0D + DataWidth =3D 0x04u;=0D + }=0D +=0D + if (CpuSaveState->x64.IO_DWord & 0x01u) {=0D + IoInfo->IoType =3D EFI_SMM_SAVE_STATE_IO_TYPE_INPUT;=0D + } else {=0D + IoInfo->IoType =3D EFI_SMM_SAVE_STATE_IO_TYPE_OUTPUT;=0D + }=0D +=0D + if ((IoInfo->IoType =3D=3D EFI_SMM_SAVE_STATE_IO_TYPE_INPUT) || (IoInf= o->IoType =3D=3D EFI_SMM_SAVE_STATE_IO_TYPE_OUTPUT)) {=0D + SmmCpuFeaturesReadSaveStateRegister (CpuIndex, EFI_SMM_SAVE_STATE_RE= GISTER_RAX, DataWidth, &IoInfo->IoData);=0D + }=0D +=0D + return EFI_SUCCESS;=0D + }=0D +=0D + // Convert Register to a register lookup table index=0D + return ReadSaveStateRegisterByIndex (CpuIndex, GetRegisterIndex (Registe= r), Width, Buffer);=0D +}=0D +=0D +/**=0D + Writes an SMM Save State register on the target processor. If this func= tion=0D + returns EFI_UNSUPPORTED, then the caller is responsible for writing the= =0D + SMM Save Sate register.=0D +=0D + @param[in] CpuIndex The index of the CPU to write the SMM Save State. = The=0D + value must be between 0 and the NumberOfCpus field = in=0D + the System Management System Table (SMST).=0D + @param[in] Register The SMM Save State register to write.=0D + @param[in] Width The number of bytes to write to the CPU save state.= =0D + @param[in] Buffer Upon entry, this holds the new CPU register value.= =0D +=0D + @retval EFI_SUCCESS The register was written to Save State.=0D + @retval EFI_INVALID_PARAMTER Buffer is NULL.=0D + @retval EFI_UNSUPPORTED This function does not support writing Reg= ister.=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +InternalSmmCpuFeaturesWriteSaveStateRegister (=0D + IN UINTN CpuIndex,=0D + IN EFI_SMM_SAVE_STATE_REGISTER Register,=0D + IN UINTN Width,=0D + IN CONST VOID *Buffer=0D + )=0D +{=0D + UINTN RegisterIndex;=0D + AMD_SMRAM_SAVE_STATE_MAP *CpuSaveState;=0D +=0D + //=0D + // Writes to EFI_SMM_SAVE_STATE_REGISTER_LMA are ignored=0D + //=0D + if (Register =3D=3D EFI_SMM_SAVE_STATE_REGISTER_LMA) {=0D + return EFI_SUCCESS;=0D + }=0D +=0D + //=0D + // Writes to EFI_SMM_SAVE_STATE_REGISTER_IO are not supported=0D + //=0D + if (Register =3D=3D EFI_SMM_SAVE_STATE_REGISTER_IO) {=0D + return EFI_NOT_FOUND;=0D + }=0D +=0D + //=0D + // Convert Register to a register lookup table index=0D + //=0D + RegisterIndex =3D GetRegisterIndex (Register);=0D + if (RegisterIndex =3D=3D 0) {=0D + return EFI_NOT_FOUND;=0D + }=0D +=0D + CpuSaveState =3D gSmst->CpuSaveState[CpuIndex];=0D +=0D + //=0D + // Do not write non-writable SaveState, because it will cause exception.= =0D + //=0D + if (!mSmmCpuWidthOffset[RegisterIndex].Writeable) {=0D + return EFI_UNSUPPORTED;=0D + }=0D +=0D + //=0D + // Check CPU mode=0D + //=0D + if (mSmmSaveStateRegisterLma =3D=3D EFI_SMM_SAVE_STATE_REGISTER_LMA_32BI= T) {=0D + //=0D + // If 32-bit mode width is zero, then the specified register can not b= e accessed=0D + //=0D + if (mSmmCpuWidthOffset[RegisterIndex].Width32 =3D=3D 0) {=0D + return EFI_NOT_FOUND;=0D + }=0D +=0D + //=0D + // If Width is bigger than the 32-bit mode width, then the specified r= egister can not be accessed=0D + //=0D + if (Width > mSmmCpuWidthOffset[RegisterIndex].Width32) {=0D + return EFI_INVALID_PARAMETER;=0D + }=0D +=0D + //=0D + // Write SMM State register=0D + //=0D + ASSERT (CpuSaveState !=3D NULL);=0D + CopyMem ((UINT8 *)CpuSaveState + mSmmCpuWidthOffset[RegisterIndex].Off= set32, Buffer, Width);=0D + } else {=0D + //=0D + // If 64-bit mode width is zero, then the specified register can not b= e accessed=0D + //=0D + if (mSmmCpuWidthOffset[RegisterIndex].Width64 =3D=3D 0) {=0D + return EFI_NOT_FOUND;=0D + }=0D +=0D + //=0D + // If Width is bigger than the 64-bit mode width, then the specified r= egister can not be accessed=0D + //=0D + if (Width > mSmmCpuWidthOffset[RegisterIndex].Width64) {=0D + return EFI_INVALID_PARAMETER;=0D + }=0D +=0D + //=0D + // Write lower 32-bits of SMM State register=0D + //=0D + CopyMem ((UINT8 *)CpuSaveState + mSmmCpuWidthOffset[RegisterIndex].Off= set64Lo, Buffer, MIN (4, Width));=0D + if (Width >=3D 4) {=0D + //=0D + // Write upper 32-bits of SMM State register=0D + //=0D + CopyMem ((UINT8 *)CpuSaveState + mSmmCpuWidthOffset[RegisterIndex].O= ffset64Hi, (UINT8 *)Buffer + 4, Width - 4);=0D + }=0D + }=0D +=0D + return EFI_SUCCESS;=0D +}=0D --=20 2.25.1