From mboxrd@z Thu Jan  1 00:00:00 1970
Received: from NAM02-BN1-obe.outbound.protection.outlook.com (NAM02-BN1-obe.outbound.protection.outlook.com [40.107.212.83])
 by mx.groups.io with SMTP id smtpd.web11.43439.1683182382042973844
 for <devel@edk2.groups.io>;
 Wed, 03 May 2023 23:39:42 -0700
Authentication-Results: mx.groups.io;
 dkim=fail reason="body hash did not verify" header.i=@amd.com header.s=selector1 header.b=iZSA+51s;
 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.212.83, mailfrom: abdullateef.attar@amd.com)
ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none;
 b=bQryYlzrGiy5gXKcsnz3k6oq9kRQFqC3MtCEDsJ1JA8XUu1GGcrqJWR3+V/PjDXFuI919qq3TX7FypjNmjkm/o9SSiEXXHHFr/58/5iaYYrxWRUoJGVjS84FPDTA5CGAViYhYYiK0mgLrOxSzrrbxBZEqnB490MwoA4+ybVYEMF++OOD+4vA1v6sCM71B776q2FSqjWJk9MZ0/lxzCzK5alMdVXDBEdWUAJPXXwE6j4g3kWIT5PMeRPAbGgG5kbGJK3OfCFDfyowR1ER43bggXCHhGMqRPZnX029/ItiSkdL8arq8BiykFh09lbpRduaudkfzE2XRpY19mpR321vPQ==
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=OxZeYctvkMzGdarPBA7PsefzE8DdHIqOsjIC5CXgTTU=;
 b=G0OwkHBsNt2kWwoWUZ8eKD3gYBiUiOwrOD5UaDLSsk+KHsnMDhl7noPIORohN9kGnQPptjMc1UY7gSWD6TeKG5CS6zmrI8KK4UQSUjxqZpg6A/wm9iH6pXdzvLolsfTXgHGyu8PaspNYyo8eBpOcCuB43vzWDGGEVF15exHt6S+/KOrGWDfN2RisF1dAkyrB8kuguurP0KrV2HQXqqg9zrx5KvWzCPM0fvguneWI3hMGx2wU5+kZlmaLRJEU0ijBuKQRzTNWJQDktCzrZD0yHpc9fFucfOoUzLuP3zdkJU8+Sarj5uAQsewoOPM27TVHiV7sa37BlZA+IlQTYhPFMQ==
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=OxZeYctvkMzGdarPBA7PsefzE8DdHIqOsjIC5CXgTTU=;
 b=iZSA+51sxEsOmay5m/2tEBNiQglgbLdNmxLJK/GtXHK2kUm/Aa2BqfaEuMnuWtDve8j49kWU5fkoAHGqhygjyFSAqgOUj0bstleWGK0HGicjs0OevBrnG0RaV4YAaDkl742HCJIkcXXsnHjymNmOnI0HySFpGiW33eFn6mUNISk=
Received: from BN7PR02CA0026.namprd02.prod.outlook.com (2603:10b6:408:20::39)
 by DM6PR12MB4401.namprd12.prod.outlook.com (2603:10b6:5:2a9::15) with
 Microsoft SMTP Server (version=TLS1_2,
 cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6363.22; Thu, 4 May
 2023 06:39:37 +0000
Received: from BN8NAM11FT116.eop-nam11.prod.protection.outlook.com
 (2603:10b6:408:20:cafe::99) by BN7PR02CA0026.outlook.office365.com
 (2603:10b6:408:20::39) with Microsoft SMTP Server (version=TLS1_2,
 cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6363.26 via Frontend
 Transport; Thu, 4 May 2023 06:39:37 +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=SATLEXMB03.amd.com; pr=C
Received: from SATLEXMB03.amd.com (165.204.84.17) by
 BN8NAM11FT116.mail.protection.outlook.com (10.13.176.67) with Microsoft SMTP
 Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id
 15.20.6363.26 via Frontend Transport; Thu, 4 May 2023 06:39:36 +0000
Received: from SATLEXMB06.amd.com (10.181.40.147) by SATLEXMB03.amd.com
 (10.181.40.144) with Microsoft SMTP Server (version=TLS1_2,
 cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2375.34; Thu, 4 May
 2023 01:39:36 -0500
Received: from SATLEXMB04.amd.com (10.181.40.145) by SATLEXMB06.amd.com
 (10.181.40.147) with Microsoft SMTP Server (version=TLS1_2,
 cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2375.34; Thu, 4 May
 2023 01:39:36 -0500
Received: from BLR-LAB-SFW01.amd.com (10.180.168.240) by SATLEXMB04.amd.com
 (10.181.40.145) with Microsoft SMTP Server id 15.1.2375.34 via Frontend
 Transport; Thu, 4 May 2023 01:39:33 -0500
From: "Abdul Lateef Attar" <abdattar@amd.com>
To: <devel@edk2.groups.io>
CC: Abdul Lateef Attar <AbdulLateef.Attar@amd.com>, Paul Grimes
	<paul.grimes@amd.com>, Abner Chang <abner.chang@amd.com>, Eric Dong
	<eric.dong@intel.com>, Ray Ni <ray.ni@intel.com>, Rahul Kumar
	<rahul1.kumar@intel.com>, Gerd Hoffmann <kraxel@redhat.com>, "Abdul Lateef
 Attar" <abdattar@amd.com>
Subject: [PATCH v10 3/9] UefiCpuPkg: Implements MmSaveStateLib library instance
Date: Thu, 4 May 2023 12:09:15 +0530
Message-ID: <561757cfd427fcadd74aeec12e483c34a5b45dea.1683182178.git.abdattar@amd.com>
X-Mailer: git-send-email 2.25.1
In-Reply-To: <cover.1683182178.git.abdattar@amd.com>
References: <cover.1683182178.git.abdattar@amd.com>
MIME-Version: 1.0
Return-Path: AbdulLateef.Attar@amd.com
X-EOPAttributedMessage: 0
X-MS-PublicTrafficType: Email
X-MS-TrafficTypeDiagnostic: BN8NAM11FT116:EE_|DM6PR12MB4401:EE_
X-MS-Office365-Filtering-Correlation-Id: 94b89c38-d085-4036-bb9a-08db4c6a546d
X-MS-Exchange-SenderADCheck: 1
X-MS-Exchange-AntiSpam-Relay: 0
X-Microsoft-Antispam: BCL:0;
X-Microsoft-Antispam-Message-Info: 
	+8HSeHVvBoEO2V8BHGIVNd/kwoLdPGy42ybdjYoCr654XhYTqkmCiJ9875koVf2jMJ49pc/NhfQacPbdelJuKMZHyjUPsopi5sgNWuWh3+ymQi0uLc+qY2MaFdydm5dq4n5zEFB17WR82eMn2plHEYAOfh2N+amGZIPEmWqG+sZMr+w1CPDgQm1Pet3fhlq+l7D3CwqOMYDGLm8NlqIfDYYZ+htBBximxAo5C9Atw/d8RHlxSkILgoiBHg8eksehMRJP5zwwcZTUMIDeZZht/ByWxVOd7H0lnzyeUO3Yvx/CGgg2VuMRh6lcX531nuvE96iYIdESvs0lTc7UErxGdprVwfeX1TVPJCPBbjxKdg0iZ+0QtIfv34S8CjH7gC+O23xR0lNaG4eOKPnfh7phcSFnHFy5n5Q8JfJmyFmAVn8Tk10pkiouWpO3pXLUnf4UEf9zIHs1rDGYwGcByJPdDVYwTaZsXZGCfA2SsLWT/uqtqsGxCCKyiKfEX9NWpRjfsfHDAvHGzISzM9w/es6JDDO9+SN7dIAkzyAJ6BmKj+EgGcE1NhfiyvU+deB6gytHPGAKG5ERyttF4Ac3XII9ohvQJgR6s9Ot2Ife6OoTkRzhA7crxDyQxmyj1C2VJC87gmYn/IWMjSe20FI3/n6k3EiBe2TlU3wu/0lmDXZIKRoOiY7rg0DlNQRxtQA2ny7P4DNfdmCqdiuTcskqPqQ9MvoTMzBl4ahwz3fVfNCVnTs=
X-Forefront-Antispam-Report: 
	CIP:165.204.84.17;CTRY:US;LANG:en;SCL:1;SRV:;IPV:CAL;SFV:NSPM;H:SATLEXMB03.amd.com;PTR:InfoDomainNonexistent;CAT:NONE;SFS:(13230028)(6029001)(4636009)(346002)(396003)(39860400002)(376002)(136003)(451199021)(46966006)(36840700001)(40470700004)(336012)(426003)(36860700001)(2616005)(7696005)(82310400005)(186003)(47076005)(2906002)(30864003)(26005)(54906003)(83380400001)(6916009)(5660300002)(70206006)(966005)(40460700003)(70586007)(8936002)(8676002)(4326008)(6666004)(478600001)(36756003)(82740400003)(356005)(316002)(81166007)(40480700001)(41300700001)(36900700001);DIR:OUT;SFP:1101;
X-OriginatorOrg: amd.com
X-MS-Exchange-CrossTenant-OriginalArrivalTime: 04 May 2023 06:39:36.9310
 (UTC)
X-MS-Exchange-CrossTenant-Network-Message-Id: 94b89c38-d085-4036-bb9a-08db4c6a546d
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=[SATLEXMB03.amd.com]
X-MS-Exchange-CrossTenant-AuthSource: 
	BN8NAM11FT116.eop-nam11.prod.protection.outlook.com
X-MS-Exchange-CrossTenant-AuthAs: Anonymous
X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem
X-MS-Exchange-Transport-CrossTenantHeadersStamped: DM6PR12MB4401
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain

From: Abdul Lateef Attar <AbdulLateef.Attar@amd.com>

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

Implements MmSaveStateLib Library class for
AMD cpu family.

Cc: Paul Grimes <paul.grimes@amd.com>
Cc: Abner Chang <abner.chang@amd.com>
Cc: Eric Dong <eric.dong@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
Cc: Rahul Kumar <rahul1.kumar@intel.com>
Cc: Gerd Hoffmann <kraxel@redhat.com>

Signed-off-by: Abdul Lateef Attar <abdattar@amd.com>
Reviewed-by: Abner Chang <abner.chang@amd.com>
---
 UefiCpuPkg/UefiCpuPkg.dsc                     |   3 +
 .../MmSaveStateLib/AmdMmSaveStateLib.inf      |  28 ++
 .../Library/MmSaveStateLib/MmSaveState.h      | 102 ++++++
 .../Library/MmSaveStateLib/AmdMmSaveState.c   | 309 ++++++++++++++++++
 .../MmSaveStateLib/MmSaveStateCommon.c        | 138 ++++++++
 5 files changed, 580 insertions(+)
 create mode 100644 UefiCpuPkg/Library/MmSaveStateLib/AmdMmSaveStateLib.inf
 create mode 100644 UefiCpuPkg/Library/MmSaveStateLib/MmSaveState.h
 create mode 100644 UefiCpuPkg/Library/MmSaveStateLib/AmdMmSaveState.c
 create mode 100644 UefiCpuPkg/Library/MmSaveStateLib/MmSaveStateCommon.c

diff --git a/UefiCpuPkg/UefiCpuPkg.dsc b/UefiCpuPkg/UefiCpuPkg.dsc
index 593c11cc7482..8b0cb02a80e8 100644
--- a/UefiCpuPkg/UefiCpuPkg.dsc
+++ b/UefiCpuPkg/UefiCpuPkg.dsc
@@ -2,6 +2,7 @@
 #  UefiCpuPkg Package
 #
 #  Copyright (c) 2007 - 2022, Intel Corporation. All rights reserved.<BR>
+#  Copyright (C) 2023 Advanced Micro Devices, Inc. All rights reserved.<BR=
>
 #
 #  SPDX-License-Identifier: BSD-2-Clause-Patent
 #
@@ -99,6 +100,7 @@ [LibraryClasses.common.DXE_SMM_DRIVER]
   MemoryAllocationLib|MdePkg/Library/SmmMemoryAllocationLib/SmmMemoryAlloc=
ationLib.inf
   HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
   CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/SmmCpuE=
xceptionHandlerLib.inf
+  MmSaveStateLib|UefiCpuPkg/Library/MmSaveStateLib/AmdMmSaveStateLib.inf
=20
 [LibraryClasses.common.MM_STANDALONE]
   MmServicesTableLib|MdePkg/Library/StandaloneMmServicesTableLib/Standalon=
eMmServicesTableLib.inf
@@ -182,6 +184,7 @@ [Components.IA32, Components.X64]
     <LibraryClasses>
       UnitTestResultReportLib|UnitTestFrameworkPkg/Library/UnitTestResultR=
eportLib/UnitTestResultReportLibConOut.inf
   }
+  UefiCpuPkg/Library/MmSaveStateLib/AmdMmSaveStateLib.inf
=20
 [Components.X64]
   UefiCpuPkg/Library/CpuExceptionHandlerLib/UnitTest/DxeCpuExceptionHandle=
rLibUnitTest.inf
diff --git a/UefiCpuPkg/Library/MmSaveStateLib/AmdMmSaveStateLib.inf b/Uefi=
CpuPkg/Library/MmSaveStateLib/AmdMmSaveStateLib.inf
new file mode 100644
index 000000000000..426eb87a4d1f
--- /dev/null
+++ b/UefiCpuPkg/Library/MmSaveStateLib/AmdMmSaveStateLib.inf
@@ -0,0 +1,28 @@
+## @file
+# MM Smram save state service lib.
+#
+# This is MM Smram save state service lib that provide service to read and
+# save savestate area registers.
+#
+# Copyright (C) 2023 Advanced Micro Devices, Inc. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    =3D 1.29
+  BASE_NAME                      =3D AmdMmSaveStateLib
+  FILE_GUID                      =3D FB7D0A60-E8D4-4EFA-90AA-B357BC569879
+  MODULE_TYPE                    =3D DXE_SMM_DRIVER
+  VERSION_STRING                 =3D 1.0
+  LIBRARY_CLASS                  =3D MmSaveStateLib
+
+[Sources]
+  MmSaveState.h
+  MmSaveStateCommon.c
+  AmdMmSaveState.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  UefiCpuPkg/UefiCpuPkg.dec
diff --git a/UefiCpuPkg/Library/MmSaveStateLib/MmSaveState.h b/UefiCpuPkg/L=
ibrary/MmSaveStateLib/MmSaveState.h
new file mode 100644
index 000000000000..80b10450013b
--- /dev/null
+++ b/UefiCpuPkg/Library/MmSaveStateLib/MmSaveState.h
@@ -0,0 +1,102 @@
+/** @file
+  SMRAM Save State Map header file.
+
+  Copyright (c) 2010 - 2019, Intel Corporation. All rights reserved.<BR>
+  Copyright (C) 2023 Advanced Micro Devices, Inc. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef MM_SAVESTATE_H_
+#define MM_SAVESTATE_H_
+
+#include <Uefi/UefiBaseType.h>
+#include <Protocol/SmmCpu.h>
+#include <Library/DebugLib.h>
+#include <Library/MmSaveStateLib.h>
+#include <Library/SmmServicesTableLib.h>
+#include <Library/BaseMemoryLib.h>
+
+// EFER register LMA bit
+#define LMA  BIT10
+
+// Macro used to simplify the lookup table entries of type CPU_MM_SAVE_STA=
TE_REGISTER_RANGE
+#define MM_REGISTER_RANGE(Start, End)  { Start, End, End - Start + 1 }
+
+#define MM_SAVE_STATE_REGISTER_MAX_INDEX  2
+
+// Structure used to describe a range of registers
+typedef struct {
+  EFI_MM_SAVE_STATE_REGISTER    Start;
+  EFI_MM_SAVE_STATE_REGISTER    End;
+  UINTN                         Length;
+} CPU_MM_SAVE_STATE_REGISTER_RANGE;
+
+// Structure used to build a lookup table to retrieve the widths and offse=
ts
+// associated with each supported EFI_MM_SAVE_STATE_REGISTER value
+
+typedef struct {
+  UINT8      Width32;
+  UINT8      Width64;
+  UINT16     Offset32;
+  UINT16     Offset64Lo;
+  UINT16     Offset64Hi;
+  BOOLEAN    Writeable;
+} CPU_MM_SAVE_STATE_LOOKUP_ENTRY;
+
+/**
+  Returns LMA value of the Processor.
+
+  @param[in]  CpuIndex  Specifies the zero-based index of the CPU save sta=
te.
+
+  @retval     UINT8     returns LMA bit value.
+**/
+UINT8
+EFIAPI
+MmSaveStateGetRegisterLma (
+  IN UINTN  CpuIndex
+  );
+
+/**
+  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 mCpuWidthOffset[] associated with Register
+
+**/
+UINTN
+EFIAPI
+MmSaveStateGetRegisterIndex (
+  IN EFI_MM_SAVE_STATE_REGISTER  Register
+  );
+
+/**
+  Read a CPU Save State register on the target processor.
+
+  This function abstracts the differences that whether the CPU Save State =
register is in the
+  IA32 CPU Save State Map or X64 CPU Save State Map.
+
+  This function supports reading a CPU Save State register in SMBase reloc=
ation handler.
+
+  @param[in]  CpuIndex       Specifies the zero-based index of the CPU sav=
e state.
+  @param[in]  RegisterIndex  Index into mCpuWidthOffset[] 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 valu=
e 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 S=
tate of Processor.
+  @retval EFI_INVALID_PARAMTER  This or Buffer is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+MmSaveStateReadRegisterByIndex (
+  IN UINTN  CpuIndex,
+  IN UINTN  RegisterIndex,
+  IN UINTN  Width,
+  OUT VOID  *Buffer
+  );
+
+#endif
diff --git a/UefiCpuPkg/Library/MmSaveStateLib/AmdMmSaveState.c b/UefiCpuPk=
g/Library/MmSaveStateLib/AmdMmSaveState.c
new file mode 100644
index 000000000000..cb5dbfc45886
--- /dev/null
+++ b/UefiCpuPkg/Library/MmSaveStateLib/AmdMmSaveState.c
@@ -0,0 +1,309 @@
+/** @file
+Provides services to access SMRAM Save State Map
+
+Copyright (c) 2010 - 2019, Intel Corporation. All rights reserved.<BR>
+Copyright (C) 2023 Advanced Micro Devices, Inc. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "MmSaveState.h"
+#include <Register/Amd/SmramSaveStateMap.h>
+#include <Library/BaseLib.h>
+
+#define EFER_ADDRESS                           0xC0000080ul
+#define MM_SAVE_STATE_REGISTER_SMMREVID_INDEX  1
+
+// Macro used to simplify the lookup table entries of type CPU_MM_SAVE_STA=
TE_LOOKUP_ENTRY
+#define MM_CPU_OFFSET(Field)  OFFSET_OF (AMD_SMRAM_SAVE_STATE_MAP, Field)
+
+// Lookup table used to retrieve the widths and offsets associated with ea=
ch
+// supported EFI_MM_SAVE_STATE_REGISTER value
+CONST CPU_MM_SAVE_STATE_LOOKUP_ENTRY  mCpuWidthOffset[] =3D {
+  { 0, 0, 0,                            0,                                =
    FALSE },                                        //  Reserved
+
+  //
+  // Internally defined CPU Save State Registers. Not defined in PI SMM CP=
U Protocol.
+  //
+  { 4, 4, MM_CPU_OFFSET (x86.SMMRevId), MM_CPU_OFFSET (x64.SMMRevId),     =
    0, FALSE},                                      // MM_SAVE_STATE_REGIST=
ER_SMMREVID_INDEX  =3D 1
+
+  //
+  // CPU Save State registers defined in PI SMM CPU Protocol.
+  //
+  { 4, 8, MM_CPU_OFFSET (x86.GDTBase),  MM_CPU_OFFSET (x64._GDTRBaseLoDwor=
d), MM_CPU_OFFSET (x64._GDTRBaseHiDword), FALSE},   //  EFI_MM_SAVE_STATE_R=
EGISTER_GDTBASE  =3D 4
+  { 0, 8, 0,                            MM_CPU_OFFSET (x64._IDTRBaseLoDwor=
d), MM_CPU_OFFSET (x64._IDTRBaseLoDword), FALSE},   //  EFI_MM_SAVE_STATE_R=
EGISTER_IDTBASE  =3D 5
+  { 0, 8, 0,                            MM_CPU_OFFSET (x64._LDTRBaseLoDwor=
d), MM_CPU_OFFSET (x64._LDTRBaseLoDword), FALSE},   //  EFI_MM_SAVE_STATE_R=
EGISTER_LDTBASE  =3D 6
+  { 0, 2, 0,                            MM_CPU_OFFSET (x64._GDTRLimit),   =
    0, FALSE},                                      //  EFI_MM_SAVE_STATE_R=
EGISTER_GDTLIMIT =3D 7
+  { 0, 2, 0,                            MM_CPU_OFFSET (x64._IDTRLimit),   =
    0, FALSE},                                      //  EFI_MM_SAVE_STATE_R=
EGISTER_IDTLIMIT =3D 8
+  { 0, 4, 0,                            MM_CPU_OFFSET (x64._LDTRLimit),   =
    0, FALSE},                                      //  EFI_MM_SAVE_STATE_R=
EGISTER_LDTLIMIT =3D 9
+  { 0, 0, 0,                            0,                                =
    0, FALSE},                                      //  EFI_MM_SAVE_STATE_R=
EGISTER_LDTINFO  =3D 10
+  { 4, 2, MM_CPU_OFFSET (x86._ES),      MM_CPU_OFFSET (x64._ES),          =
    0, FALSE},                                      //  EFI_MM_SAVE_STATE_R=
EGISTER_ES       =3D 20
+  { 4, 2, MM_CPU_OFFSET (x86._CS),      MM_CPU_OFFSET (x64._CS),          =
    0, FALSE},                                      //  EFI_MM_SAVE_STATE_R=
EGISTER_CS       =3D 21
+  { 4, 2, MM_CPU_OFFSET (x86._SS),      MM_CPU_OFFSET (x64._SS),          =
    0, FALSE},                                      //  EFI_MM_SAVE_STATE_R=
EGISTER_SS       =3D 22
+  { 4, 2, MM_CPU_OFFSET (x86._DS),      MM_CPU_OFFSET (x64._DS),          =
    0, FALSE},                                      //  EFI_MM_SAVE_STATE_R=
EGISTER_DS       =3D 23
+  { 4, 2, MM_CPU_OFFSET (x86._FS),      MM_CPU_OFFSET (x64._FS),          =
    0, FALSE},                                      //  EFI_MM_SAVE_STATE_R=
EGISTER_FS       =3D 24
+  { 4, 2, MM_CPU_OFFSET (x86._GS),      MM_CPU_OFFSET (x64._GS),          =
    0, FALSE},                                      //  EFI_MM_SAVE_STATE_R=
EGISTER_GS       =3D 25
+  { 0, 2, 0,                            MM_CPU_OFFSET (x64._LDTR),        =
    0, FALSE},                                      //  EFI_MM_SAVE_STATE_R=
EGISTER_LDTR_SEL =3D 26
+  { 0, 2, 0,                            MM_CPU_OFFSET (x64._TR),          =
    0, FALSE},                                      //  EFI_MM_SAVE_STATE_R=
EGISTER_TR_SEL   =3D 27
+  { 4, 8, MM_CPU_OFFSET (x86._DR7),     MM_CPU_OFFSET (x64._DR7),         =
    MM_CPU_OFFSET (x64._DR7)         + 4, FALSE},   //  EFI_MM_SAVE_STATE_R=
EGISTER_DR7      =3D 28
+  { 4, 8, MM_CPU_OFFSET (x86._DR6),     MM_CPU_OFFSET (x64._DR6),         =
    MM_CPU_OFFSET (x64._DR6)         + 4, FALSE},   //  EFI_MM_SAVE_STATE_R=
EGISTER_DR6      =3D 29
+  { 0, 8, 0,                            MM_CPU_OFFSET (x64._R8),          =
    MM_CPU_OFFSET (x64._R8)          + 4, TRUE},    //  EFI_MM_SAVE_STATE_R=
EGISTER_R8       =3D 30
+  { 0, 8, 0,                            MM_CPU_OFFSET (x64._R9),          =
    MM_CPU_OFFSET (x64._R9)          + 4, TRUE},    //  EFI_MM_SAVE_STATE_R=
EGISTER_R9       =3D 31
+  { 0, 8, 0,                            MM_CPU_OFFSET (x64._R10),         =
    MM_CPU_OFFSET (x64._R10)         + 4, TRUE},    //  EFI_MM_SAVE_STATE_R=
EGISTER_R10      =3D 32
+  { 0, 8, 0,                            MM_CPU_OFFSET (x64._R11),         =
    MM_CPU_OFFSET (x64._R11)         + 4, TRUE},    //  EFI_MM_SAVE_STATE_R=
EGISTER_R11      =3D 33
+  { 0, 8, 0,                            MM_CPU_OFFSET (x64._R12),         =
    MM_CPU_OFFSET (x64._R12)         + 4, TRUE},    //  EFI_MM_SAVE_STATE_R=
EGISTER_R12      =3D 34
+  { 0, 8, 0,                            MM_CPU_OFFSET (x64._R13),         =
    MM_CPU_OFFSET (x64._R13)         + 4, TRUE},    //  EFI_MM_SAVE_STATE_R=
EGISTER_R13      =3D 35
+  { 0, 8, 0,                            MM_CPU_OFFSET (x64._R14),         =
    MM_CPU_OFFSET (x64._R14)         + 4, TRUE},    //  EFI_MM_SAVE_STATE_R=
EGISTER_R14      =3D 36
+  { 0, 8, 0,                            MM_CPU_OFFSET (x64._R15),         =
    MM_CPU_OFFSET (x64._R15)         + 4, TRUE},    //  EFI_MM_SAVE_STATE_R=
EGISTER_R15      =3D 37
+  { 4, 8, MM_CPU_OFFSET (x86._EAX),     MM_CPU_OFFSET (x64._RAX),         =
    MM_CPU_OFFSET (x64._RAX)         + 4, TRUE},    //  EFI_MM_SAVE_STATE_R=
EGISTER_RAX      =3D 38
+  { 4, 8, MM_CPU_OFFSET (x86._EBX),     MM_CPU_OFFSET (x64._RBX),         =
    MM_CPU_OFFSET (x64._RBX)         + 4, TRUE},    //  EFI_MM_SAVE_STATE_R=
EGISTER_RBX      =3D 39
+  { 4, 8, MM_CPU_OFFSET (x86._ECX),     MM_CPU_OFFSET (x64._RCX),         =
    MM_CPU_OFFSET (x64._RCX)         + 4, TRUE},    //  EFI_MM_SAVE_STATE_R=
EGISTER_RBX      =3D 39
+  { 4, 8, MM_CPU_OFFSET (x86._EDX),     MM_CPU_OFFSET (x64._RDX),         =
    MM_CPU_OFFSET (x64._RDX)         + 4, TRUE},    //  EFI_MM_SAVE_STATE_R=
EGISTER_RDX      =3D 41
+  { 4, 8, MM_CPU_OFFSET (x86._ESP),     MM_CPU_OFFSET (x64._RSP),         =
    MM_CPU_OFFSET (x64._RSP)         + 4, TRUE},    //  EFI_MM_SAVE_STATE_R=
EGISTER_RSP      =3D 42
+  { 4, 8, MM_CPU_OFFSET (x86._EBP),     MM_CPU_OFFSET (x64._RBP),         =
    MM_CPU_OFFSET (x64._RBP)         + 4, TRUE},    //  EFI_MM_SAVE_STATE_R=
EGISTER_RBP      =3D 43
+  { 4, 8, MM_CPU_OFFSET (x86._ESI),     MM_CPU_OFFSET (x64._RSI),         =
    MM_CPU_OFFSET (x64._RSI)         + 4, TRUE},    //  EFI_MM_SAVE_STATE_R=
EGISTER_RSI      =3D 44
+  { 4, 8, MM_CPU_OFFSET (x86._EDI),     MM_CPU_OFFSET (x64._RDI),         =
    MM_CPU_OFFSET (x64._RDI)         + 4, TRUE},    //  EFI_MM_SAVE_STATE_R=
EGISTER_RDI      =3D 45
+  { 4, 8, MM_CPU_OFFSET (x86._EIP),     MM_CPU_OFFSET (x64._RIP),         =
    MM_CPU_OFFSET (x64._RIP)         + 4, TRUE},    //  EFI_MM_SAVE_STATE_R=
EGISTER_RIP      =3D 46
+
+  { 4, 8, MM_CPU_OFFSET (x86._EFLAGS),  MM_CPU_OFFSET (x64._RFLAGS),      =
    MM_CPU_OFFSET (x64._RFLAGS)      + 4, TRUE},    //  EFI_MM_SAVE_STATE_R=
EGISTER_RFLAGS   =3D 51
+  { 4, 8, MM_CPU_OFFSET (x86._CR0),     MM_CPU_OFFSET (x64._CR0),         =
    MM_CPU_OFFSET (x64._CR0)         + 4, FALSE},   //  EFI_MM_SAVE_STATE_R=
EGISTER_CR0      =3D 52
+  { 4, 8, MM_CPU_OFFSET (x86._CR3),     MM_CPU_OFFSET (x64._CR3),         =
    MM_CPU_OFFSET (x64._CR3)         + 4, FALSE},   //  EFI_MM_SAVE_STATE_R=
EGISTER_CR3      =3D 53
+  { 0, 8, 0,                            MM_CPU_OFFSET (x64._CR4),         =
    MM_CPU_OFFSET (x64._CR4)         + 4, FALSE},   //  EFI_MM_SAVE_STATE_R=
EGISTER_CR4      =3D 54
+  { 0, 0, 0,                            0,                                =
    0     }
+};
+
+/**
+  Read a save state register on the target processor.  If this function
+  returns EFI_UNSUPPORTED, then the caller is responsible for reading the
+  MM Save State register.
+
+  @param[in]  CpuIndex  The index of the CPU to read the Save State regist=
er.
+                        The value must be between 0 and the NumberOfCpus f=
ield in
+                        the System Management System Table (SMST).
+  @param[in]  Register  The MM Save State register to read.
+  @param[in]  Width     The number of bytes to read from the CPU save stat=
e.
+  @param[out] Buffer    Upon return, this holds the CPU register value rea=
d
+                        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 Reg=
ister.
+  @retval EFI_NOT_FOUND         If desired Register not found.
+**/
+EFI_STATUS
+EFIAPI
+MmSaveStateReadRegister (
+  IN  UINTN                       CpuIndex,
+  IN  EFI_MM_SAVE_STATE_REGISTER  Register,
+  IN  UINTN                       Width,
+  OUT VOID                        *Buffer
+  )
+{
+  UINT32                     SmmRevId;
+  EFI_MM_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[CpuInde=
x];
+
+  // Check for special EFI_MM_SAVE_STATE_REGISTER_LMA
+  if (Register =3D=3D EFI_MM_SAVE_STATE_REGISTER_LMA) {
+    // Only byte access is supported for this register
+    if (Width !=3D 1) {
+      return EFI_INVALID_PARAMETER;
+    }
+
+    *(UINT8 *)Buffer =3D MmSaveStateGetRegisterLma (CpuIndex);
+
+    return EFI_SUCCESS;
+  }
+
+  // Check for special EFI_MM_SAVE_STATE_REGISTER_IO
+  if (Register =3D=3D EFI_MM_SAVE_STATE_REGISTER_IO) {
+    //
+    // Get SMM Revision ID
+    //
+    MmSaveStateReadRegisterByIndex (CpuIndex, MM_SAVE_STATE_REGISTER_SMMRE=
VID_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_MM_SAVE_STATE_IO_INFO *)Buffer;
+    ZeroMem (IoInfo, sizeof (EFI_MM_SAVE_STATE_IO_INFO));
+
+    IoInfo->IoPort =3D (UINT16)(CpuSaveState->x64.IO_DWord >> 16u);
+
+    if (CpuSaveState->x64.IO_DWord & 0x10u) {
+      IoInfo->IoWidth =3D EFI_MM_SAVE_STATE_IO_WIDTH_UINT8;
+      DataWidth       =3D 0x01u;
+    } else if (CpuSaveState->x64.IO_DWord & 0x20u) {
+      IoInfo->IoWidth =3D EFI_MM_SAVE_STATE_IO_WIDTH_UINT16;
+      DataWidth       =3D 0x02u;
+    } else {
+      IoInfo->IoWidth =3D EFI_MM_SAVE_STATE_IO_WIDTH_UINT32;
+      DataWidth       =3D 0x04u;
+    }
+
+    if (CpuSaveState->x64.IO_DWord & 0x01u) {
+      IoInfo->IoType =3D EFI_MM_SAVE_STATE_IO_TYPE_INPUT;
+    } else {
+      IoInfo->IoType =3D EFI_MM_SAVE_STATE_IO_TYPE_OUTPUT;
+    }
+
+    if ((IoInfo->IoType =3D=3D EFI_MM_SAVE_STATE_IO_TYPE_INPUT) || (IoInfo=
->IoType =3D=3D EFI_MM_SAVE_STATE_IO_TYPE_OUTPUT)) {
+      MmSaveStateReadRegister (CpuIndex, EFI_MM_SAVE_STATE_REGISTER_RAX, D=
ataWidth, &IoInfo->IoData);
+    }
+
+    return EFI_SUCCESS;
+  }
+
+  // Convert Register to a register lookup table index
+  return MmSaveStateReadRegisterByIndex (CpuIndex, MmSaveStateGetRegisterI=
ndex (Register), Width, Buffer);
+}
+
+/**
+  Writes a save state register on the target processor.  If this function
+  returns EFI_UNSUPPORTED, then the caller is responsible for writing the
+  MM save state register.
+
+  @param[in] CpuIndex  The index of the CPU to write the MM Save State.  T=
he
+                       value must be between 0 and the NumberOfCpus field =
in
+                       the System Management System Table (SMST).
+  @param[in] Register  The MM 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 Reg=
ister.
+  @retval EFI_NOT_FOUND         If desired Register not found.
+**/
+EFI_STATUS
+EFIAPI
+MmSaveStateWriteRegister (
+  IN UINTN                       CpuIndex,
+  IN EFI_MM_SAVE_STATE_REGISTER  Register,
+  IN UINTN                       Width,
+  IN CONST VOID                  *Buffer
+  )
+{
+  UINTN                     RegisterIndex;
+  AMD_SMRAM_SAVE_STATE_MAP  *CpuSaveState;
+
+  //
+  // Writes to EFI_MM_SAVE_STATE_REGISTER_LMA are ignored
+  //
+  if (Register =3D=3D EFI_MM_SAVE_STATE_REGISTER_LMA) {
+    return EFI_SUCCESS;
+  }
+
+  //
+  // Writes to EFI_MM_SAVE_STATE_REGISTER_IO are not supported
+  //
+  if (Register =3D=3D EFI_MM_SAVE_STATE_REGISTER_IO) {
+    return EFI_NOT_FOUND;
+  }
+
+  //
+  // Convert Register to a register lookup table index
+  //
+  RegisterIndex =3D MmSaveStateGetRegisterIndex (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 (!mCpuWidthOffset[RegisterIndex].Writeable) {
+    return EFI_UNSUPPORTED;
+  }
+
+  //
+  // Check CPU mode
+  //
+  if (MmSaveStateGetRegisterLma (CpuIndex) =3D=3D EFI_MM_SAVE_STATE_REGIST=
ER_LMA_32BIT) {
+    //
+    // If 32-bit mode width is zero, then the specified register can not b=
e accessed
+    //
+    if (mCpuWidthOffset[RegisterIndex].Width32 =3D=3D 0) {
+      return EFI_NOT_FOUND;
+    }
+
+    //
+    // If Width is bigger than the 32-bit mode width, then the specified r=
egister can not be accessed
+    //
+    if (Width > mCpuWidthOffset[RegisterIndex].Width32) {
+      return EFI_INVALID_PARAMETER;
+    }
+
+    //
+    // Write SMM State register
+    //
+    ASSERT (CpuSaveState !=3D NULL);
+    CopyMem ((UINT8 *)CpuSaveState + mCpuWidthOffset[RegisterIndex].Offset=
32, Buffer, Width);
+  } else {
+    //
+    // If 64-bit mode width is zero, then the specified register can not b=
e accessed
+    //
+    if (mCpuWidthOffset[RegisterIndex].Width64 =3D=3D 0) {
+      return EFI_NOT_FOUND;
+    }
+
+    //
+    // If Width is bigger than the 64-bit mode width, then the specified r=
egister can not be accessed
+    //
+    if (Width > mCpuWidthOffset[RegisterIndex].Width64) {
+      return EFI_INVALID_PARAMETER;
+    }
+
+    //
+    // Write lower 32-bits of SMM State register
+    //
+    CopyMem ((UINT8 *)CpuSaveState + mCpuWidthOffset[RegisterIndex].Offset=
64Lo, Buffer, MIN (4, Width));
+    if (Width >=3D 4) {
+      //
+      // Write upper 32-bits of SMM State register
+      //
+      CopyMem ((UINT8 *)CpuSaveState + mCpuWidthOffset[RegisterIndex].Offs=
et64Hi, (UINT8 *)Buffer + 4, Width - 4);
+    }
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Returns LMA value of the Processor.
+
+  @param[in]  CpuIndex  Specifies the zero-based index of the CPU save sta=
te.
+
+  @retval     UINT8     returns LMA bit value.
+**/
+UINT8
+EFIAPI
+MmSaveStateGetRegisterLma (
+  IN UINTN  CpuIndex
+  )
+{
+  UINT32  LMAValue;
+
+  LMAValue =3D (UINT32)AsmReadMsr64 (EFER_ADDRESS) & LMA;
+  if (LMAValue) {
+    return EFI_MM_SAVE_STATE_REGISTER_LMA_64BIT;
+  }
+
+  return EFI_MM_SAVE_STATE_REGISTER_LMA_32BIT;
+}
diff --git a/UefiCpuPkg/Library/MmSaveStateLib/MmSaveStateCommon.c b/UefiCp=
uPkg/Library/MmSaveStateLib/MmSaveStateCommon.c
new file mode 100644
index 000000000000..9e920bfba7a2
--- /dev/null
+++ b/UefiCpuPkg/Library/MmSaveStateLib/MmSaveStateCommon.c
@@ -0,0 +1,138 @@
+/** @file
+  Provides common supporting function to access SMRAM Save State Map
+
+  Copyright (c) 2010 - 2019, Intel Corporation. All rights reserved.<BR>
+  Copyright (C) 2023 Advanced Micro Devices, Inc. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "MmSaveState.h"
+#include <Library/BaseLib.h>
+#include <Library/CpuLib.h>
+
+#define CPUID_VERSION_INFO       0x01
+#define CPUID_EXTENDED_FUNCTION  0x80000000
+#define CPUID_EXTENDED_CPU_SIG   0x80000001
+
+// Table used by MmSaveStateGetRegisterIndex() to convert an EFI_MM_SAVE_S=
TATE_REGISTER
+// value to an index into a table of type CPU_MM_SAVE_STATE_LOOKUP_ENTRY
+CONST CPU_MM_SAVE_STATE_REGISTER_RANGE  mCpuRegisterRanges[] =3D {
+  MM_REGISTER_RANGE (EFI_MM_SAVE_STATE_REGISTER_GDTBASE, EFI_MM_SAVE_STATE=
_REGISTER_LDTINFO),
+  MM_REGISTER_RANGE (EFI_MM_SAVE_STATE_REGISTER_ES,      EFI_MM_SAVE_STATE=
_REGISTER_RIP),
+  MM_REGISTER_RANGE (EFI_MM_SAVE_STATE_REGISTER_RFLAGS,  EFI_MM_SAVE_STATE=
_REGISTER_CR4),
+  { (EFI_MM_SAVE_STATE_REGISTER)0,                       (EFI_MM_SAVE_STAT=
E_REGISTER)0,      0}
+};
+
+extern CONST CPU_MM_SAVE_STATE_LOOKUP_ENTRY  mCpuWidthOffset[];
+
+/**
+  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 mCpuWidthOffset[] associated with Register
+
+**/
+UINTN
+EFIAPI
+MmSaveStateGetRegisterIndex (
+  IN EFI_MM_SAVE_STATE_REGISTER  Register
+  )
+{
+  UINTN  Index;
+  UINTN  Offset;
+
+  for (Index =3D 0, Offset =3D MM_SAVE_STATE_REGISTER_MAX_INDEX; mCpuRegis=
terRanges[Index].Length !=3D 0; Index++) {
+    if ((Register >=3D mCpuRegisterRanges[Index].Start) && (Register <=3D =
mCpuRegisterRanges[Index].End)) {
+      return Register - mCpuRegisterRanges[Index].Start + Offset;
+    }
+
+    Offset +=3D mCpuRegisterRanges[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 reloc=
ation handler.
+
+  @param[in]  CpuIndex       Specifies the zero-based index of the CPU sav=
e state.
+  @param[in]  RegisterIndex  Index into mCpuWidthOffset[] 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 valu=
e 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 S=
tate of Processor.
+  @retval EFI_INVALID_PARAMTER  This or Buffer is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+MmSaveStateReadRegisterByIndex (
+  IN UINTN  CpuIndex,
+  IN UINTN  RegisterIndex,
+  IN UINTN  Width,
+  OUT VOID  *Buffer
+  )
+{
+  if (RegisterIndex =3D=3D 0) {
+    return EFI_NOT_FOUND;
+  }
+
+  if (MmSaveStateGetRegisterLma (CpuIndex) =3D=3D EFI_MM_SAVE_STATE_REGIST=
ER_LMA_32BIT) {
+    //
+    // If 32-bit mode width is zero, then the specified register can not b=
e accessed
+    //
+    if (mCpuWidthOffset[RegisterIndex].Width32 =3D=3D 0) {
+      return EFI_NOT_FOUND;
+    }
+
+    //
+    // If Width is bigger than the 32-bit mode width, then the specified r=
egister can not be accessed
+    //
+    if (Width > mCpuWidthOffset[RegisterIndex].Width32) {
+      return EFI_INVALID_PARAMETER;
+    }
+
+    //
+    // Write return buffer
+    //
+    ASSERT (gSmst->CpuSaveState[CpuIndex] !=3D NULL);
+    CopyMem (Buffer, (UINT8 *)gSmst->CpuSaveState[CpuIndex] + mCpuWidthOff=
set[RegisterIndex].Offset32, Width);
+  } else {
+    //
+    // If 64-bit mode width is zero, then the specified register can not b=
e accessed
+    //
+    if (mCpuWidthOffset[RegisterIndex].Width64 =3D=3D 0) {
+      return EFI_NOT_FOUND;
+    }
+
+    //
+    // If Width is bigger than the 64-bit mode width, then the specified r=
egister can not be accessed
+    //
+    if (Width > mCpuWidthOffset[RegisterIndex].Width64) {
+      return EFI_INVALID_PARAMETER;
+    }
+
+    //
+    // Write lower 32-bits of return buffer
+    //
+    CopyMem (Buffer, (UINT8 *)gSmst->CpuSaveState[CpuIndex] + mCpuWidthOff=
set[RegisterIndex].Offset64Lo, MIN (4, Width));
+    if (Width > 4) {
+      //
+      // Write upper 32-bits of return buffer
+      //
+      CopyMem ((UINT8 *)Buffer + 4, (UINT8 *)gSmst->CpuSaveState[CpuIndex]=
 + mCpuWidthOffset[RegisterIndex].Offset64Hi, Width - 4);
+    }
+  }
+
+  return EFI_SUCCESS;
+}
--=20
2.25.1