aboutsummaryrefslogtreecommitdiff
path: root/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature
diff options
context:
space:
mode:
authorSiyuan Wang <wangsiyuanbuaa@gmail.com>2013-07-25 15:14:15 +0800
committerBruce Griffith <Bruce.Griffith@se-eng.com>2013-08-04 05:40:37 +0200
commitaffe85fbc8a13d35960aa92ae87cbb6330ad253f (patch)
tree9c1ace69f12b06b6544faf041994aa4288fb2e45 /src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature
parentae8d06969bdde9b1250bc3c4ad93f5db408dae98 (diff)
AMD Kabini: Add AGESA/PI code for new processor family
Change-Id: Icb6f64e2e3cfd678fb4fb4f13f0e4b678d5acc4a Signed-off-by: Siyuan Wang <SiYuan.Wang@amd.com> Signed-off-by: Siyuan Wang <wangsiyuanbuaa@gmail.com> Reviewed-by: Nick Dill <nick.dill@se-eng.com> Tested-by: Bruce Griffith <bruce.griffith@se-eng.com> Reviewed-on: http://review.coreboot.org/3836 Tested-by: build bot (Jenkins) Reviewed-by: Martin Roth <martin.roth@se-eng.com>
Diffstat (limited to 'src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature')
-rw-r--r--src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/PreserveMailbox.h97
-rw-r--r--src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuApm.c194
-rw-r--r--src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuApm.h127
-rw-r--r--src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuC6State.c260
-rw-r--r--src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuC6State.h156
-rw-r--r--src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuCacheFlushOnHalt.c199
-rw-r--r--src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuCacheInit.c751
-rw-r--r--src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuCacheInit.h138
-rw-r--r--src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuCdit.c347
-rw-r--r--src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuCoreLeveling.c374
-rw-r--r--src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuCpb.c175
-rw-r--r--src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuCpb.h133
-rw-r--r--src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuCrat.c513
-rw-r--r--src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuCrat.h85
-rw-r--r--src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuDmi.c872
-rw-r--r--src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuFeatureLeveling.c265
-rw-r--r--src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuFeatures.c283
-rw-r--r--src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuFeatures.h281
-rw-r--r--src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuHtc.c201
-rw-r--r--src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuHtc.h130
-rw-r--r--src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuIoCstate.c207
-rw-r--r--src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuIoCstate.h283
-rw-r--r--src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuL3Features.h399
-rw-r--r--src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuMsgBasedC1e.h127
-rw-r--r--src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuPrefetchMode.h110
-rw-r--r--src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuPsi.c213
-rw-r--r--src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuPsi.h130
-rw-r--r--src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuPstateGather.c410
-rw-r--r--src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuPstateHpcMode.h98
-rw-r--r--src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuPstateLeveling.c1100
-rw-r--r--src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuPstateTables.c940
-rw-r--r--src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuPstateTables.h314
-rw-r--r--src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuSlit.c398
-rw-r--r--src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuSrat.c618
-rw-r--r--src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuTdpLimiting.h129
-rw-r--r--src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuWhea.c288
36 files changed, 11345 insertions, 0 deletions
diff --git a/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/PreserveMailbox.h b/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/PreserveMailbox.h
new file mode 100644
index 0000000000..9417814ed1
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/PreserveMailbox.h
@@ -0,0 +1,97 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * AMD AGESA CPU Preserve Registers used for AP Mailbox.
+ *
+ * Save and Restore the normal feature content of the registers being used for
+ * the AP Mailbox.
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: CPU/Feature
+ * @e \$Revision: 84150 $ @e \$Date: 2012-12-12 15:46:25 -0600 (Wed, 12 Dec 2012) $
+ *
+ */
+/*
+ ******************************************************************************
+ *
+ * Copyright (c) 2008 - 2013, Advanced Micro Devices, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Advanced Micro Devices, Inc. nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ ******************************************************************************
+ */
+
+#ifndef _PRESERVE_MAILBOX_H_
+#define _PRESERVE_MAILBOX_H_
+
+/*----------------------------------------------------------------------------------------
+ * M I X E D (Definitions And Macros / Typedefs, Structures, Enums)
+ *----------------------------------------------------------------------------------------
+ */
+#define MAX_PRESERVE_REGISTER_ENTRIES 2 ///< There is room on the heap for up to this per node.
+
+/// Reference to a save buffer.
+typedef UINT32 (*MAILBOX_REGISTER_SAVE_ENTRY) [MAX_PRESERVE_REGISTER_ENTRIES];
+
+/*----------------------------------------------------------------------------------------
+ * D E F I N I T I O N S A N D M A C R O S
+ *----------------------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------------------
+ * T Y P E D E F S A N D S T R U C T U R E S
+ *----------------------------------------------------------------------------------------
+ */
+
+/**
+ * Family specific mailbox register descriptor.
+ *
+ * Describes a register and bits within the register used as the mailbox.
+ */
+typedef struct {
+ PCI_ADDR Register; ///< The PCI address of a mailbox register.
+ UINT32 Mask; ///< The mask of bits used in Register as the mailbox.
+} PRESERVE_MAILBOX_FAMILY_REGISTER;
+
+/**
+ * Descriptor for family specific save-restore.
+ *
+ * Provide a list of the register offsets to save-restore on each node. Optionally, zero the
+ * register instead of restoring it.
+ */
+typedef struct {
+ UINT16 Revision; ///< Interface version
+ // Public Data.
+ BOOLEAN IsZeroOnCold; ///< On a cold boot, zero the register instead of restore.
+ PRESERVE_MAILBOX_FAMILY_REGISTER *RegisterList; ///< The list of registers, terminated by ILLEGAL_SBDFO.
+} PRESERVE_MAILBOX_FAMILY_SERVICES;
+
+
+/*----------------------------------------------------------------------------------------
+ * F U N C T I O N S P R O T O T Y P E
+ *----------------------------------------------------------------------------------------
+ */
+
+#endif // _PRESERVE_MAILBOX_H_
diff --git a/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuApm.c b/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuApm.c
new file mode 100644
index 0000000000..d5b3bd77ce
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuApm.c
@@ -0,0 +1,194 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * AMD AGESA CPU Application Power Management (APM) feature support code.
+ *
+ * Contains code that declares the AGESA CPU APM related APIs
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: CPU/Feature
+ * @e \$Revision: 85057 $ @e \$Date: 2012-12-27 01:35:49 -0600 (Thu, 27 Dec 2012) $
+ *
+ */
+/*
+ ******************************************************************************
+ *
+ * Copyright (c) 2008 - 2013, Advanced Micro Devices, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Advanced Micro Devices, Inc. nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ ******************************************************************************
+ */
+
+/*----------------------------------------------------------------------------------------
+ * M O D U L E S U S E D
+ *----------------------------------------------------------------------------------------
+ */
+#include "AGESA.h"
+#include "GeneralServices.h"
+#include "cpuFamilyTranslation.h"
+#include "cpuApicUtilities.h"
+#include "cpuFeatures.h"
+#include "cpuApm.h"
+#include "Filecode.h"
+CODE_GROUP (G1_PEICC)
+RDATA_GROUP (G1_PEICC)
+
+#define FILECODE PROC_CPU_FEATURE_CPUAPM_FILECODE
+
+/*----------------------------------------------------------------------------------------
+ * D E F I N I T I O N S A N D M A C R O S
+ *----------------------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------------------
+ * T Y P E D E F S A N D S T R U C T U R E S
+ *----------------------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------------------
+ * P R O T O T Y P E S O F L O C A L F U N C T I O N S
+ *----------------------------------------------------------------------------------------
+ */
+VOID
+EnableApmOnSocket (
+ IN AMD_CONFIG_PARAMS *StdHeader
+ );
+
+/*----------------------------------------------------------------------------------------
+ * E X P O R T E D F U N C T I O N S
+ *----------------------------------------------------------------------------------------
+ */
+extern CPU_FAMILY_SUPPORT_TABLE ApmFamilyServiceTable;
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * Should Application Power Management (APM) be enabled
+ *
+ * @param[in] PlatformConfig Contains the runtime modifiable feature input data.
+ * @param[in] StdHeader Config Handle for library, services.
+ *
+ * @retval TRUE APM is supported.
+ * @retval FALSE APM cannot be enabled.
+ *
+ */
+STATIC BOOLEAN
+IsApmFeatureEnabled (
+ IN PLATFORM_CONFIGURATION *PlatformConfig,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ UINT32 Socket;
+ BOOLEAN IsEnabled;
+ APM_FAMILY_SERVICES *FamilyServices;
+
+ IsEnabled = FALSE;
+
+ for (Socket = 0; Socket < GetPlatformNumberOfSockets (); Socket++) {
+ if (IsProcessorPresent (Socket, StdHeader)) {
+ GetFeatureServicesOfSocket (&ApmFamilyServiceTable, Socket, (CONST VOID **)&FamilyServices, StdHeader);
+ if (FamilyServices != NULL) {
+ if (FamilyServices->IsApmSupported (FamilyServices, PlatformConfig, Socket, StdHeader)) {
+ IsEnabled = TRUE;
+ break;
+ }
+ }
+ }
+ }
+ return IsEnabled;
+}
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * Enable Application Power Management (APM)
+ *
+ * @param[in] EntryPoint Timepoint designator.
+ * @param[in] PlatformConfig Contains the runtime modifiable feature input data.
+ * @param[in] StdHeader Config Handle for library, services.
+ *
+ * @retval AGESA_SUCCESS Always succeeds.
+ *
+ */
+STATIC AGESA_STATUS
+InitializeApmFeature (
+ IN UINT64 EntryPoint,
+ IN PLATFORM_CONFIGURATION *PlatformConfig,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ UINT32 BscSocket;
+ UINT32 Ignored;
+ UINT32 Socket;
+ UINT32 NumberOfSockets;
+ AP_TASK TaskPtr;
+ AGESA_STATUS IgnoredSts;
+
+ IDS_HDT_CONSOLE (CPU_TRACE, " APM mode is enabled\n");
+
+ IdentifyCore (StdHeader, &BscSocket, &Ignored, &Ignored, &IgnoredSts);
+ NumberOfSockets = GetPlatformNumberOfSockets ();
+
+ TaskPtr.FuncAddress.PfApTask = EnableApmOnSocket;
+ TaskPtr.DataTransfer.DataSizeInDwords = 0;
+ TaskPtr.ExeFlags = WAIT_FOR_CORE;
+
+ for (Socket = 0; Socket < NumberOfSockets; Socket++) {
+ if (IsProcessorPresent (Socket, StdHeader)) {
+ if (Socket != BscSocket) {
+ ApUtilRunCodeOnSocketCore ((UINT8) Socket, 0, &TaskPtr, StdHeader);
+ }
+ }
+ }
+
+ EnableApmOnSocket (StdHeader);
+ return AGESA_SUCCESS;
+}
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * AP task to enable APM
+ *
+ * @param[in] StdHeader Config Handle for library, services.
+ *
+ */
+VOID
+EnableApmOnSocket (
+ IN AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ APM_FAMILY_SERVICES *FamilyServices;
+
+ GetFeatureServicesOfCurrentCore (&ApmFamilyServiceTable, (CONST VOID **)&FamilyServices, StdHeader);
+ FamilyServices->EnableApmOnSocket (FamilyServices,
+ StdHeader);
+}
+
+CONST CPU_FEATURE_DESCRIPTOR ROMDATA CpuFeatureApm =
+{
+ CpuApm,
+ (CPU_FEAT_BEFORE_RELINQUISH_AP | CPU_FEAT_AFTER_RESUME_MTRR_SYNC),
+ IsApmFeatureEnabled,
+ InitializeApmFeature
+};
diff --git a/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuApm.h b/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuApm.h
new file mode 100644
index 0000000000..ce418ec6a8
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuApm.h
@@ -0,0 +1,127 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * AMD AGESA CPU Application Power Management (APM) Functions declarations.
+ *
+ * Contains code that declares the AGESA CPU APM related APIs
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: CPU/Feature
+ * @e \$Revision: 84150 $ @e \$Date: 2012-12-12 15:46:25 -0600 (Wed, 12 Dec 2012) $
+ *
+ */
+/*
+ ******************************************************************************
+ *
+ * Copyright (c) 2008 - 2013, Advanced Micro Devices, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Advanced Micro Devices, Inc. nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ ******************************************************************************
+ */
+
+#ifndef _CPU_APM_H_
+#define _CPU_APM_H_
+
+/*----------------------------------------------------------------------------------------
+ * M I X E D (Definitions And Macros / Typedefs, Structures, Enums)
+ *----------------------------------------------------------------------------------------
+ */
+// Forward declaration needed for multi-structure mutual references
+AGESA_FORWARD_DECLARATION (APM_FAMILY_SERVICES);
+
+/*----------------------------------------------------------------------------------------
+ * D E F I N I T I O N S A N D M A C R O S
+ *----------------------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------------------
+ * T Y P E D E F S A N D S T R U C T U R E S
+ *----------------------------------------------------------------------------------------
+ */
+
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * Family specific call to check if Application Power Management (APM) is supported.
+ *
+ * @param[in] ApmServices APM services.
+ * @param[in] PlatformConfig Contains the runtime modifiable feature input data.
+ * @param[in] Socket Zero-based socket number.
+ * @param[in] StdHeader Config Handle for library, services.
+ *
+ * @retval TRUE APM is supported.
+ * @retval FALSE APM is not supported.
+ *
+ */
+typedef BOOLEAN F_APM_IS_SUPPORTED (
+ IN APM_FAMILY_SERVICES *CpbServices,
+ IN PLATFORM_CONFIGURATION *PlatformConfig,
+ IN UINT32 Socket,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ );
+
+/// Reference to a Method.
+typedef F_APM_IS_SUPPORTED *PF_APM_IS_SUPPORTED;
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * Family specific call to enable APM.
+ *
+ * @param[in] ApmServices APM services.
+ * @param[in] StdHeader Config Handle for library, services.
+ *
+ * @return Family specific error value.
+ *
+ */
+typedef AGESA_STATUS F_APM_INIT (
+ IN APM_FAMILY_SERVICES *ApmServices,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ );
+
+/// Reference to a Method.
+typedef F_APM_INIT *PF_APM_INIT;
+
+/**
+ * Provide the interface to the APM Family Specific Services.
+ *
+ * Use the methods or data in this struct to adapt the feature code to a specific cpu family or model (or stepping!).
+ * Each supported Family must provide an implementation for all methods in this interface, even if the
+ * implementation is a CommonReturn().
+ */
+struct _APM_FAMILY_SERVICES {
+ UINT16 Revision; ///< Interface version
+ // Public Methods.
+ PF_APM_IS_SUPPORTED IsApmSupported; ///< Method: Family specific call to check if APM is supported.
+ PF_APM_INIT EnableApmOnSocket; ///< Method: Family specific call to enable APM.
+};
+
+
+/*----------------------------------------------------------------------------------------
+ * F U N C T I O N S P R O T O T Y P E
+ *----------------------------------------------------------------------------------------
+ */
+
+#endif // _CPU_APM_H_
diff --git a/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuC6State.c b/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuC6State.c
new file mode 100644
index 0000000000..9a1d937097
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuC6State.c
@@ -0,0 +1,260 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * AMD AGESA CPU C6 feature support code.
+ *
+ * Contains code that declares the AGESA CPU C6 related APIs
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: CPU/Feature
+ * @e \$Revision: 84150 $ @e \$Date: 2012-12-12 15:46:25 -0600 (Wed, 12 Dec 2012) $
+ *
+ */
+/*
+ ******************************************************************************
+ *
+ * Copyright (c) 2008 - 2013, Advanced Micro Devices, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Advanced Micro Devices, Inc. nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ ******************************************************************************
+ */
+
+/*----------------------------------------------------------------------------------------
+ * M O D U L E S U S E D
+ *----------------------------------------------------------------------------------------
+ */
+#include "AGESA.h"
+#include "amdlib.h"
+#include "Ids.h"
+#include "cpuRegisters.h"
+#include "cpuEarlyInit.h"
+#include "GeneralServices.h"
+#include "cpuFamilyTranslation.h"
+#include "OptionMultiSocket.h"
+#include "cpuApicUtilities.h"
+#include "cpuServices.h"
+#include "cpuFeatures.h"
+#include "cpuC6State.h"
+#include "Filecode.h"
+CODE_GROUP (G1_PEICC)
+RDATA_GROUP (G1_PEICC)
+
+#define FILECODE PROC_CPU_FEATURE_CPUC6STATE_FILECODE
+
+/*----------------------------------------------------------------------------------------
+ * D E F I N I T I O N S A N D M A C R O S
+ *----------------------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------------------
+ * T Y P E D E F S A N D S T R U C T U R E S
+ *----------------------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------------------
+ * P R O T O T Y P E S O F L O C A L F U N C T I O N S
+ *----------------------------------------------------------------------------------------
+ */
+VOID
+STATIC
+EnableC6OnSocket (
+ IN VOID *EntryPoint,
+ IN AMD_CONFIG_PARAMS *StdHeader,
+ IN AMD_CPU_EARLY_PARAMS *CpuEarlyParams
+ );
+
+/*----------------------------------------------------------------------------------------
+ * E X P O R T E D F U N C T I O N S
+ *----------------------------------------------------------------------------------------
+ */
+extern CPU_FAMILY_SUPPORT_TABLE C6FamilyServiceTable;
+extern OPTION_MULTISOCKET_CONFIGURATION OptionMultiSocketConfiguration;
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * Should C6 be enabled
+ *
+ * @param[in] PlatformConfig Contains the runtime modifiable feature input data.
+ * @param[in] StdHeader Config Handle for library, services.
+ *
+ * @retval TRUE C6 is supported.
+ * @retval FALSE C6 cannot be enabled.
+ *
+ */
+BOOLEAN
+STATIC
+IsC6FeatureEnabled (
+ IN PLATFORM_CONFIGURATION *PlatformConfig,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ UINT32 Socket;
+ BOOLEAN IsEnabled;
+ C6_FAMILY_SERVICES *FamilyServices;
+
+ IsEnabled = FALSE;
+ if (PlatformConfig->CStateMode == CStateModeC6) {
+ IsEnabled = TRUE;
+ for (Socket = 0; Socket < GetPlatformNumberOfSockets (); Socket++) {
+ if (IsProcessorPresent (Socket, StdHeader)) {
+ GetFeatureServicesOfSocket (&C6FamilyServiceTable, Socket, (CONST VOID **)&FamilyServices, StdHeader);
+ if ((FamilyServices == NULL) || !FamilyServices->IsC6Supported (FamilyServices, Socket, PlatformConfig, StdHeader)) {
+ IsEnabled = FALSE;
+ break;
+ }
+ }
+ }
+ }
+ return IsEnabled;
+}
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * Enable the C6 C-state
+ *
+ * @param[in] EntryPoint Timepoint designator.
+ * @param[in] PlatformConfig Contains the runtime modifiable feature input data.
+ * @param[in] StdHeader Config Handle for library, services.
+ *
+ * @retval AGESA_SUCCESS Always succeeds.
+ *
+ */
+AGESA_STATUS
+STATIC
+InitializeC6Feature (
+ IN UINT64 EntryPoint,
+ IN PLATFORM_CONFIGURATION *PlatformConfig,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ UINT32 BscSocket;
+ UINT32 Ignored;
+ UINT32 BscCoreNum;
+ UINT32 Core;
+ UINT32 Socket;
+ UINT32 NumberOfSockets;
+ UINT32 NumberOfCores;
+ AP_TASK TaskPtr;
+ AMD_CPU_EARLY_PARAMS CpuEarlyParams;
+ C6_FAMILY_SERVICES *C6FamilyServices;
+ AGESA_STATUS IgnoredSts;
+
+ CpuEarlyParams.PlatformConfig = *PlatformConfig;
+
+ TaskPtr.FuncAddress.PfApTaskIC = EnableC6OnSocket;
+ TaskPtr.DataTransfer.DataSizeInDwords = 2;
+ TaskPtr.DataTransfer.DataPtr = &EntryPoint;
+ TaskPtr.DataTransfer.DataTransferFlags = 0;
+ TaskPtr.ExeFlags = PASS_EARLY_PARAMS;
+ OptionMultiSocketConfiguration.BscRunCodeOnAllSystemCore0s (&TaskPtr, StdHeader, &CpuEarlyParams);
+
+ if ((EntryPoint & (CPU_FEAT_AFTER_POST_MTRR_SYNC | CPU_FEAT_AFTER_RESUME_MTRR_SYNC)) != 0) {
+ // Load any required microcode patches on both normal boot and resume from S3.
+ IdentifyCore (StdHeader, &BscSocket, &Ignored, &BscCoreNum, &IgnoredSts);
+ GetFeatureServicesOfSocket (&C6FamilyServiceTable, BscSocket, (CONST VOID **)&C6FamilyServices, StdHeader);
+ if (C6FamilyServices != NULL) {
+ C6FamilyServices->ReloadMicrocodePatchAfterMemInit (StdHeader);
+ }
+
+ // run code on all APs
+ TaskPtr.DataTransfer.DataSizeInDwords = 0;
+ TaskPtr.ExeFlags = 0;
+
+ NumberOfSockets = GetPlatformNumberOfSockets ();
+
+ for (Socket = 0; Socket < NumberOfSockets; Socket++) {
+ if (IsProcessorPresent (Socket, StdHeader)) {
+ GetFeatureServicesOfSocket (&C6FamilyServiceTable, Socket, (CONST VOID **)&C6FamilyServices, StdHeader);
+ if (C6FamilyServices != NULL) {
+ // run code on all APs
+ TaskPtr.FuncAddress.PfApTask = C6FamilyServices->ReloadMicrocodePatchAfterMemInit;
+ if (GetActiveCoresInGivenSocket (Socket, &NumberOfCores, StdHeader)) {
+ for (Core = 0; Core < NumberOfCores; Core++) {
+ if ((Socket != BscSocket) || (Core != BscCoreNum)) {
+ ApUtilRunCodeOnSocketCore ((UINT8) Socket, (UINT8) Core, &TaskPtr, StdHeader);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return AGESA_SUCCESS;
+}
+
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * 'Local' core 0 task to enable C6 on it's socket.
+ *
+ * @param[in] EntryPoint Timepoint designator.
+ * @param[in] StdHeader Config Handle for library, services.
+ * @param[in] CpuEarlyParams Service parameters.
+ *
+ */
+VOID
+STATIC
+EnableC6OnSocket (
+ IN VOID *EntryPoint,
+ IN AMD_CONFIG_PARAMS *StdHeader,
+ IN AMD_CPU_EARLY_PARAMS *CpuEarlyParams
+ )
+{
+
+ C6_FAMILY_SERVICES *FamilyServices;
+
+ IDS_HDT_CONSOLE (CPU_TRACE, " C6 is enabled\n");
+
+ GetFeatureServicesOfCurrentCore (&C6FamilyServiceTable, (CONST VOID **)&FamilyServices, StdHeader);
+ FamilyServices->InitializeC6 (FamilyServices,
+ *((UINT64 *) EntryPoint),
+ &CpuEarlyParams->PlatformConfig,
+ StdHeader);
+}
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * Reload microcode patch after memory is initialized.
+ *
+ * @param[in] StdHeader Config Handle for library, services.
+ *
+ */
+VOID
+ReloadMicrocodePatchAfterMemInit (
+ IN AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ LoadMicrocodePatch (StdHeader);
+}
+
+
+CONST CPU_FEATURE_DESCRIPTOR ROMDATA CpuFeatureC6State =
+{
+ C6Cstate,
+ (CPU_FEAT_AFTER_PM_INIT | CPU_FEAT_AFTER_POST_MTRR_SYNC | CPU_FEAT_AFTER_RESUME_MTRR_SYNC | CPU_FEAT_BEFORE_RELINQUISH_AP),
+ IsC6FeatureEnabled,
+ InitializeC6Feature
+};
diff --git a/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuC6State.h b/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuC6State.h
new file mode 100644
index 0000000000..1f77ca46a3
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuC6State.h
@@ -0,0 +1,156 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * AMD AGESA CPU C6 Functions declarations.
+ *
+ * Contains code that declares the AGESA CPU C6 related APIs
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: CPU/Feature
+ * @e \$Revision: 84150 $ @e \$Date: 2012-12-12 15:46:25 -0600 (Wed, 12 Dec 2012) $
+ *
+ */
+/*
+ ******************************************************************************
+ *
+ * Copyright (c) 2008 - 2013, Advanced Micro Devices, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Advanced Micro Devices, Inc. nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ ******************************************************************************
+ */
+
+#ifndef _CPU_C6_STATE_H_
+#define _CPU_C6_STATE_H_
+
+/*----------------------------------------------------------------------------------------
+ * M I X E D (Definitions And Macros / Typedefs, Structures, Enums)
+ *----------------------------------------------------------------------------------------
+ */
+// Forward declaration needed for multi-structure mutual references
+AGESA_FORWARD_DECLARATION (C6_FAMILY_SERVICES);
+
+/*----------------------------------------------------------------------------------------
+ * D E F I N I T I O N S A N D M A C R O S
+ *----------------------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------------------
+ * T Y P E D E F S A N D S T R U C T U R E S
+ *----------------------------------------------------------------------------------------
+ */
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * Family specific call to check if C6 is supported.
+ *
+ * @param[in] C6Services C6 C-state services.
+ * @param[in] Socket Zero-based socket number.
+ * @param[in] PlatformConfig Contains the runtime modifiable feature input data.
+ * @param[in] StdHeader Config Handle for library, services.
+ *
+ * @retval TRUE C6 is supported.
+ * @retval FALSE C6 is not supported.
+ *
+ */
+typedef BOOLEAN F_C6_IS_SUPPORTED (
+ IN C6_FAMILY_SERVICES *C6Services,
+ IN UINT32 Socket,
+ IN PLATFORM_CONFIGURATION *PlatformConfig,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ );
+
+/// Reference to a Method.
+typedef F_C6_IS_SUPPORTED *PF_C6_IS_SUPPORTED;
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * Family specific call to enable C6.
+ *
+ * @param[in] C6Services C6 services.
+ * @param[in] EntryPoint Timepoint designator.
+ * @param[in] PlatformConfig Contains the runtime modifiable feature input data.
+ * @param[in] StdHeader Config Handle for library, services.
+ *
+ * @return Family specific error value.
+ *
+ */
+typedef AGESA_STATUS F_C6_INIT (
+ IN C6_FAMILY_SERVICES *C6Services,
+ IN UINT64 EntryPoint,
+ IN PLATFORM_CONFIGURATION *PlatformConfig,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ );
+
+/// Reference to a Method.
+typedef F_C6_INIT *PF_C6_INIT;
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * Family specific call to reload microcode patch after memory is initialized.
+ *
+ * @param[in] StdHeader Config Handle for library, services.
+ *
+ */
+typedef VOID F_C6_RELOAD_MICROCODE_PATCH_AFTER_MEM_INIT (
+ IN AMD_CONFIG_PARAMS *StdHeader
+ );
+
+/// Reference to a Method.
+typedef F_C6_RELOAD_MICROCODE_PATCH_AFTER_MEM_INIT *PF_C6_RELOAD_MICROCODE_PATCH_AFTER_MEM_INIT;
+
+/**
+ * Provide the interface to the C6 Family Specific Services.
+ *
+ * Use the methods or data in this struct to adapt the feature code to a specific cpu family or model (or stepping!).
+ * Each supported Family must provide an implementation for all methods in this interface, even if the
+ * implementation is a CommonReturn().
+ */
+struct _C6_FAMILY_SERVICES {
+ UINT16 Revision; ///< Interface version
+ // Public Methods.
+ PF_C6_IS_SUPPORTED IsC6Supported; ///< Method: Family specific call to check if C6 is supported.
+ PF_C6_INIT InitializeC6; ///< Method: Family specific call to enable C6.
+ PF_C6_RELOAD_MICROCODE_PATCH_AFTER_MEM_INIT ReloadMicrocodePatchAfterMemInit; ///< Method: Family specific call to reload microcode patch after memory is initialized.
+};
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * Reload microcode patch after memory is initialized.
+ *
+ * @param[in] StdHeader Config Handle for library, services.
+ *
+ */
+VOID
+ReloadMicrocodePatchAfterMemInit (
+ IN AMD_CONFIG_PARAMS *StdHeader
+ );
+
+/*----------------------------------------------------------------------------------------
+ * F U N C T I O N S P R O T O T Y P E
+ *----------------------------------------------------------------------------------------
+ */
+
+#endif // _CPU_C6_STATE_H_
diff --git a/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuCacheFlushOnHalt.c b/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuCacheFlushOnHalt.c
new file mode 100644
index 0000000000..cf7d157a7e
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuCacheFlushOnHalt.c
@@ -0,0 +1,199 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * AMD CPU Cache Flush On Halt Function.
+ *
+ * Contains code to initialize Cache Flush On Halt feature.
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: CPU
+ * @e \$Revision: 84150 $ @e \$Date: 2012-12-12 15:46:25 -0600 (Wed, 12 Dec 2012) $
+ *
+ */
+/*
+ ******************************************************************************
+ *
+ * Copyright (c) 2008 - 2013, Advanced Micro Devices, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Advanced Micro Devices, Inc. nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ ******************************************************************************
+ *----------------------------------------------------------------------------
+ */
+
+
+/*
+ *----------------------------------------------------------------------------
+ * MODULES USED
+ *
+ *----------------------------------------------------------------------------
+ */
+#include "AGESA.h"
+#include "Ids.h"
+#include "amdlib.h"
+#include "cpuRegisters.h"
+#include "cpuServices.h"
+#include "cpuFamilyTranslation.h"
+#include "cpuFeatures.h"
+#include "cpuApicUtilities.h"
+#include "OptionMultiSocket.h"
+#include "Filecode.h"
+CODE_GROUP (G2_PEI)
+RDATA_GROUP (G2_PEI)
+#define FILECODE PROC_CPU_FEATURE_CPUCACHEFLUSHONHALT_FILECODE
+/*----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+
+/*----------------------------------------------------------------------------
+ * TYPEDEFS AND STRUCTURES
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------------------
+ * E X P O R T E D F U N C T I O N S
+ *----------------------------------------------------------------------------------------
+ */
+extern CPU_FAMILY_SUPPORT_TABLE CacheFlushOnHaltFamilyServiceTable;
+extern OPTION_MULTISOCKET_CONFIGURATION OptionMultiSocketConfiguration;
+
+/*----------------------------------------------------------------------------
+ * PROTOTYPES OF LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+VOID
+STATIC
+EnableCacheFlushOnHaltOnSocket (
+ IN VOID *EntryPoint,
+ IN AMD_CONFIG_PARAMS *StdHeader,
+ IN AMD_CPU_EARLY_PARAMS *CpuEarlyParams
+ );
+
+AGESA_STATUS
+InitializeCacheFlushOnHaltFeature (
+ IN UINT64 EntryPoint,
+ IN PLATFORM_CONFIGURATION *PlatformConfig,
+ IN OUT AMD_CONFIG_PARAMS *StdHeader
+ );
+
+/*----------------------------------------------------------------------------------------
+ * P U B L I C F U N C T I O N S
+ *----------------------------------------------------------------------------------------
+ */
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * Should cache flush on halt be enabled
+ *
+ * @param[in] PlatformConfig Contains the runtime modifiable feature input data.
+ * @param[in] StdHeader Config Handle for library, services.
+ *
+ * @retval TRUE core leveling is supported.
+ * @retval FALSE core leveling cannot be enabled.
+ *
+ */
+BOOLEAN
+STATIC
+IsCFOHEnabled (
+ IN PLATFORM_CONFIGURATION *PlatformConfig,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ return (TRUE);
+}
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * InitializeCacheFlushOnHaltFeature
+ *
+ * CPU feature leveling. Enable Cpu Cache Flush On Halt Function
+ *
+ * @param[in] EntryPoint Timepoint designator.
+ * @param[in] PlatformConfig Contains the runtime modifiable feature input data.
+ * @param[in,out] StdHeader Pointer to AMD_CONFIG_PARAMS struct.
+ *
+ * @return The most severe status of any family specific service.
+ */
+AGESA_STATUS
+InitializeCacheFlushOnHaltFeature (
+ IN UINT64 EntryPoint,
+ IN PLATFORM_CONFIGURATION *PlatformConfig,
+ IN OUT AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+
+ AP_TASK TaskPtr;
+ AMD_CPU_EARLY_PARAMS CpuEarlyParams;
+
+ CpuEarlyParams.PlatformConfig = *PlatformConfig;
+
+ IDS_HDT_CONSOLE (CPU_TRACE, " Cache flush on hlt feature is enabled\n");
+ TaskPtr.FuncAddress.PfApTaskIC = EnableCacheFlushOnHaltOnSocket;
+ TaskPtr.DataTransfer.DataSizeInDwords = 2;
+ TaskPtr.DataTransfer.DataPtr = &EntryPoint;
+ TaskPtr.DataTransfer.DataTransferFlags = 0;
+ TaskPtr.ExeFlags = PASS_EARLY_PARAMS;
+ OptionMultiSocketConfiguration.BscRunCodeOnAllSystemCore0s (&TaskPtr, StdHeader, &CpuEarlyParams);
+
+ return AGESA_SUCCESS;
+}
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * 'Local' core 0 task to enable Cache Flush On Halt on it's socket.
+ *
+ * @param[in] EntryPoint Timepoint designator.
+ * @param[in] StdHeader Config Handle for library, services.
+ * @param[in] CpuEarlyParams Service parameters.
+ *
+ */
+VOID
+STATIC
+EnableCacheFlushOnHaltOnSocket (
+ IN VOID *EntryPoint,
+ IN AMD_CONFIG_PARAMS *StdHeader,
+ IN AMD_CPU_EARLY_PARAMS *CpuEarlyParams
+ )
+{
+ CPU_CFOH_FAMILY_SERVICES *FamilyServices;
+
+ GetFeatureServicesOfCurrentCore (&CacheFlushOnHaltFamilyServiceTable, (CONST VOID **)&FamilyServices, StdHeader);
+ if (FamilyServices != NULL) {
+ FamilyServices->SetCacheFlushOnHaltRegister (FamilyServices, *((UINT64 *) EntryPoint), &CpuEarlyParams->PlatformConfig, StdHeader);
+ }
+}
+
+CONST CPU_FEATURE_DESCRIPTOR ROMDATA CpuFeatureCacheFlushOnHalt =
+{
+ CacheFlushOnHalt,
+ (CPU_FEAT_AFTER_POST_MTRR_SYNC | CPU_FEAT_AFTER_RESUME_MTRR_SYNC),
+ IsCFOHEnabled,
+ InitializeCacheFlushOnHaltFeature
+};
diff --git a/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuCacheInit.c b/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuCacheInit.c
new file mode 100644
index 0000000000..b5a38b8021
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuCacheInit.c
@@ -0,0 +1,751 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * AMD CPU Execution Cache Allocation functions.
+ *
+ * Contains code for doing Execution Cache Allocation for ROM space
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: CPU
+ * @e \$Revision: 84150 $ @e \$Date: 2012-12-12 15:46:25 -0600 (Wed, 12 Dec 2012) $
+ *
+ */
+/*
+ ******************************************************************************
+ *
+ * Copyright (c) 2008 - 2013, Advanced Micro Devices, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Advanced Micro Devices, Inc. nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ ******************************************************************************
+ */
+
+
+/*
+ *----------------------------------------------------------------------------
+ * MODULES USED
+ *
+ *----------------------------------------------------------------------------
+ */
+#include "AGESA.h"
+#include "amdlib.h"
+#include "Ids.h"
+#include "cpuRegisters.h"
+#include "Topology.h"
+#include "cpuServices.h"
+#include "GeneralServices.h"
+#include "cpuFamilyTranslation.h"
+#include "cpuCacheInit.h"
+#include "heapManager.h"
+#include "Filecode.h"
+CODE_GROUP (G1_PEICC)
+RDATA_GROUP (G1_PEICC)
+
+#define FILECODE PROC_CPU_FEATURE_CPUCACHEINIT_FILECODE
+/*----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *----------------------------------------------------------------------------
+ */
+// 4G - 1, ~max ROM space
+#define SIZE_INFINITE_EXE_CACHE 0xFFFFFFFFul
+
+/*----------------------------------------------------------------------------
+ * TYPEDEFS AND STRUCTURES
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * L2 cache Association to Way translation table
+ *----------------------------------------------------------------------------
+ */
+CONST UINT8 ROMDATA L2AssocToL2WayTranslationTable[] =
+{
+ 0,
+ 1,
+ 2,
+ 0xFF,
+ 4,
+ 0xFF,
+ 8,
+ 0xFF,
+ 16,
+ 0xFF,
+ 32,
+ 48,
+ 64,
+ 96,
+ 128,
+ 0xFF,
+};
+
+
+/*----------------------------------------------------------------------------
+ * PROTOTYPES OF LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * EXPORTED FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+UINT8
+STATIC
+Ceiling (
+ IN UINT32 Divisor,
+ IN UINT32 Dividend
+ );
+
+UINT32
+STATIC
+CalculateOccupiedExeCache (
+ IN AMD_CONFIG_PARAMS *StdHeader
+ );
+
+VOID
+STATIC
+CompareRegions (
+ IN EXECUTION_CACHE_REGION ARegion,
+ IN EXECUTION_CACHE_REGION BRegion,
+ IN OUT MERGED_CACHE_REGION *CRegion,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ );
+
+BOOLEAN
+STATIC
+IsPowerOfTwo (
+ IN UINT32 TestNumber
+ );
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * This function will setup ROM execution cache.
+ *
+ * The execution cache regions are passed in, the max number of execution cache regions
+ * is three. Several rules are checked for compliance. If a rule test fails then one of
+ * these error suffixes will be added to the general CPU_EVENT_EXECUTION_CACHE_ALLOCATION_ERROR
+ * in the SubReason field
+ * -1 available cache size is less than requested, the ROM execution cache
+ * region has been reduced or eliminated.
+ * -2 at least one execution cache region crosses the 1MB line, the ROM execution
+ * cache size has been reduced.
+ * -3 at least one execution cache region crosses the 4GB line, the ROM execution
+ * cache size has been reduced.
+ * -4 the start address of a region is not at the boundary of cache size,
+ * the starting address has been adjusted downward
+ * -5 execution cache start address less than D0000, request is ignored
+ * -6 more than 2 execution cache regions are above 1MB, request is ignored
+ * If the start address of all three regions are zero, then no execution cache is allocated.
+ *
+ * @param[in] StdHeader Handle to config for library and services
+ * @param[in] AmdExeAddrMapPtr Pointer to the start of EXECUTION_CACHE_REGION array
+ *
+ * @retval AGESA_SUCCESS No error
+ * @retval AGESA_WARNING AGESA_CACHE_SIZE_REDUCED; AGESA_CACHE_REGIONS_ACROSS_1MB;
+ * AGESA_CACHE_REGIONS_ACROSS_4GB;
+ * @retval AGESA_ERROR AGESA_REGION_NOT_ALIGNED_ON_BOUNDARY;
+ * AGESA_CACHE_START_ADDRESS_LESS_D0000;
+ * AGESA_THREE_CACHE_REGIONS_ABOVE_1MB;
+ *
+ */
+AGESA_STATUS
+AllocateExecutionCache (
+ IN AMD_CONFIG_PARAMS *StdHeader,
+ IN EXECUTION_CACHE_REGION *AmdExeAddrMapPtr
+ )
+{
+ AGESA_STATUS AgesaStatus;
+ AMD_GET_EXE_SIZE_PARAMS AmdGetExeSize;
+ UINT32 CurrentAllocatedExeCacheSize;
+ UINT32 RemainingExecutionCacheSize;
+ UINT64 MsrData;
+ UINT64 SecondMsrData;
+ UINT32 RequestStartAddr;
+ UINT32 RequestSize;
+ UINT32 StartFixMtrr;
+ UINT32 CurrentMtrr;
+ UINT32 EndFixMtrr;
+ UINT8 i;
+ UINT8 Ignored;
+ CACHE_INFO *CacheInfoPtr;
+ CPU_SPECIFIC_SERVICES *FamilySpecificServices;
+ EXECUTION_CACHE_REGION MtrrV6;
+ EXECUTION_CACHE_REGION MtrrV7;
+ MERGED_CACHE_REGION Result;
+
+ //
+ // If start addresses of all three regions are zero, then return early
+ //
+ if (AmdExeAddrMapPtr[0].ExeCacheStartAddr == 0) {
+ if (AmdExeAddrMapPtr[1].ExeCacheStartAddr == 0) {
+ if (AmdExeAddrMapPtr[2].ExeCacheStartAddr == 0) {
+ // No regions defined by the caller
+ return AGESA_SUCCESS;
+ }
+ }
+ }
+
+ // Get available cache size for ROM execution
+ AmdGetExeSize.StdHeader = *StdHeader;
+ AgesaStatus = AmdGetAvailableExeCacheSize (&AmdGetExeSize);
+ CurrentAllocatedExeCacheSize = CalculateOccupiedExeCache (StdHeader);
+ ASSERT (CurrentAllocatedExeCacheSize <= AmdGetExeSize.AvailableExeCacheSize);
+ IDS_HDT_CONSOLE (CPU_TRACE, " Cache size available for execution cache: 0x%x\n", AmdGetExeSize.AvailableExeCacheSize);
+ RemainingExecutionCacheSize = AmdGetExeSize.AvailableExeCacheSize - CurrentAllocatedExeCacheSize;
+
+ GetCpuServicesOfCurrentCore ((CONST CPU_SPECIFIC_SERVICES **)&FamilySpecificServices, StdHeader);
+ FamilySpecificServices->GetCacheInfo (FamilySpecificServices, (CONST VOID **) &CacheInfoPtr, &Ignored, StdHeader);
+
+ // Process each request entry 0 to 2
+ for (i = 0; i < 3; i++) {
+ // Exit if no more cache available
+ if (RemainingExecutionCacheSize == 0) {
+ break;
+ }
+
+ // Skip the region if ExeCacheSize = 0
+ if (AmdExeAddrMapPtr[i].ExeCacheSize == 0) {
+ continue;
+ }
+
+ // Align starting addresses on 32K boundary
+ AmdExeAddrMapPtr[i].ExeCacheStartAddr =
+ AmdExeAddrMapPtr[i].ExeCacheStartAddr & 0xFFFF8000;
+
+ // Adjust size to multiple of 32K (rounding up)
+ if ((AmdExeAddrMapPtr[i].ExeCacheSize % 0x8000) != 0) {
+ AmdExeAddrMapPtr[i].ExeCacheSize = ((AmdExeAddrMapPtr[i].ExeCacheSize + 0x8000) & 0xFFFF8000);
+ }
+
+ // Boundary alignment check and confirm size is an even power of two
+ if ( !IsPowerOfTwo (AmdExeAddrMapPtr[i].ExeCacheSize) ||
+ ((AmdExeAddrMapPtr[i].ExeCacheStartAddr % AmdExeAddrMapPtr[i].ExeCacheSize) != 0) ) {
+ AgesaStatus = AGESA_ERROR;
+ PutEventLog (AgesaStatus,
+ (CPU_EVENT_EXECUTION_CACHE_ALLOCATION_ERROR + AGESA_REGION_NOT_ALIGNED_ON_BOUNDARY),
+ i, AmdExeAddrMapPtr[i].ExeCacheStartAddr, AmdExeAddrMapPtr[i].ExeCacheSize, 0, StdHeader);
+ break;
+ }
+
+ // Check start address boundary
+ if (AmdExeAddrMapPtr[i].ExeCacheStartAddr < 0xD0000) {
+ AgesaStatus = AGESA_ERROR;
+ PutEventLog (AgesaStatus,
+ (CPU_EVENT_EXECUTION_CACHE_ALLOCATION_ERROR + AGESA_CACHE_START_ADDRESS_LESS_D0000),
+ i, AmdExeAddrMapPtr[i].ExeCacheStartAddr, AmdExeAddrMapPtr[i].ExeCacheSize, 0, StdHeader);
+ break;
+ }
+
+ if (CacheInfoPtr->CarExeType == LimitedByL2Size) {
+ // Verify available execution cache size for region 0 to 2 request
+ if (RemainingExecutionCacheSize < AmdExeAddrMapPtr[i].ExeCacheSize) {
+ // Request is larger than available, reduce the allocation & report the change
+ AmdExeAddrMapPtr[i].ExeCacheSize = RemainingExecutionCacheSize;
+ RemainingExecutionCacheSize = 0;
+ AgesaStatus = AGESA_WARNING;
+ PutEventLog (AgesaStatus,
+ (CPU_EVENT_EXECUTION_CACHE_ALLOCATION_ERROR + AGESA_CACHE_SIZE_REDUCED),
+ i, AmdExeAddrMapPtr[i].ExeCacheStartAddr, AmdExeAddrMapPtr[i].ExeCacheSize, 0, StdHeader);
+ } else {
+ RemainingExecutionCacheSize = RemainingExecutionCacheSize - AmdExeAddrMapPtr[i].ExeCacheSize;
+ }
+ }
+ IDS_HDT_CONSOLE (CPU_TRACE, " Exe cache allocated: Base 0x%x, Size 0x%x\n", AmdExeAddrMapPtr[i].ExeCacheStartAddr, AmdExeAddrMapPtr[i].ExeCacheSize);
+
+ RequestStartAddr = AmdExeAddrMapPtr[i].ExeCacheStartAddr;
+ RequestSize = AmdExeAddrMapPtr[i].ExeCacheSize;
+
+ if (RequestStartAddr < 0x100000) {
+ // Region starts below 1MB - Fixed MTTR region,
+ // turn on modification bit: MtrrFixDramModEn
+ LibAmdMsrRead (MSR_SYS_CFG, &MsrData, StdHeader);
+ MsrData |= 0x80000;
+ LibAmdMsrWrite (MSR_SYS_CFG, &MsrData, StdHeader);
+
+
+ // Check for 1M boundary crossing
+ if ((RequestStartAddr + RequestSize) > 0x100000) {
+ // Request spans the 1M boundary, reduce the size & report the change
+ RequestSize = 0x100000 - RequestStartAddr;
+ AmdExeAddrMapPtr[i].ExeCacheSize = RequestSize;
+ AgesaStatus = AGESA_WARNING;
+ PutEventLog (AgesaStatus,
+ (CPU_EVENT_EXECUTION_CACHE_ALLOCATION_ERROR + AGESA_CACHE_REGIONS_ACROSS_1MB),
+ i, RequestStartAddr, RequestSize, 0, StdHeader);
+ }
+
+ // Find start MTTR and end MTTR for the requested region
+ StartFixMtrr = AMD_MTRR_FIX4K_BASE + ((RequestStartAddr >> 15) & 0x7);
+ EndFixMtrr = AMD_MTRR_FIX4K_BASE + ((((RequestStartAddr + RequestSize) - 1) >> 15) & 0x7);
+
+ //
+ //Check Mtrr before we use it,
+ // if Mtrr has been used, we need to recover the previously allocated size.
+ // (only work in blocks of 32K size - no splitting of ways)
+ for (CurrentMtrr = StartFixMtrr; CurrentMtrr <= EndFixMtrr; CurrentMtrr++) {
+ LibAmdMsrRead (CurrentMtrr, &MsrData, StdHeader);
+ if ((CacheInfoPtr->CarExeType == LimitedByL2Size) && (MsrData != 0)) {
+ // MTRR previously allocated, recover size
+ RemainingExecutionCacheSize = RemainingExecutionCacheSize + 0x8000;
+ } else {
+ // Allocate this MTRR
+ MsrData = WP_IO;
+ LibAmdMsrWrite (CurrentMtrr, &MsrData, StdHeader);
+ }
+ }
+ // Turn off modification bit: MtrrFixDramModEn
+ LibAmdMsrRead (MSR_SYS_CFG, &MsrData, StdHeader);
+ MsrData &= 0xFFFFFFFFFFF7FFFFULL;
+ LibAmdMsrWrite (MSR_SYS_CFG, &MsrData, StdHeader);
+
+
+ } else {
+ // Region above 1MB - Variable MTTR region
+ // Need to check both VarMTRRs for each requested region for match or overlap
+ //
+
+ // Check for 4G boundary crossing (using size-1 to keep in 32bit math range)
+ if ((0xFFFFFFFFUL - RequestStartAddr) < (RequestSize - 1)) {
+ RequestSize = (0xFFFFFFFFUL - RequestStartAddr) + 1;
+ AgesaStatus = AGESA_WARNING;
+ AmdExeAddrMapPtr[i].ExeCacheSize = RequestSize;
+ PutEventLog (AgesaStatus,
+ (CPU_EVENT_EXECUTION_CACHE_ALLOCATION_ERROR + AGESA_CACHE_REGIONS_ACROSS_4GB),
+ i, RequestStartAddr, RequestSize, 0, StdHeader);
+ }
+ LibAmdMsrRead (AMD_MTRR_VARIABLE_BASE6, &MsrData, StdHeader);
+ MtrrV6.ExeCacheStartAddr = ((UINT32) MsrData) & 0xFFFFF000UL;
+ LibAmdMsrRead (AMD_MTRR_VARIABLE_BASE6 + 1, &MsrData, StdHeader);
+ MtrrV6.ExeCacheSize = (0xFFFFFFFFUL - (((UINT32) MsrData) & 0xFFFFF000UL)) + 1;
+
+ LibAmdMsrRead (AMD_MTRR_VARIABLE_BASE7, &MsrData, StdHeader);
+ MtrrV7.ExeCacheStartAddr = ((UINT32) MsrData) & 0xFFFFF000UL;
+ LibAmdMsrRead (AMD_MTRR_VARIABLE_BASE7 + 1, &MsrData, StdHeader);
+ MtrrV7.ExeCacheSize = (0xFFFFFFFFUL - (((UINT32) MsrData) & 0xFFFFF000UL)) + 1;
+
+ CompareRegions (AmdExeAddrMapPtr[i], MtrrV6, &Result, StdHeader);
+ if (Result.OverlapType == EmptySet) {
+ // MTRR6 is empty. Allocate request into MTRR6.
+ // Note: since all merges are moved down to MTRR6, if MTRR6 is empty so should MTRR7 also be empty
+ MtrrV6.ExeCacheStartAddr = AmdExeAddrMapPtr[i].ExeCacheStartAddr;
+ MtrrV6.ExeCacheSize = AmdExeAddrMapPtr[i].ExeCacheSize;
+ } else if ((Result.OverlapType == Disjoint) ||
+ (Result.OverlapType == NotCombinable)) {
+ // MTRR6 is in use, and request does not overlap with MTRR6, check MTRR7
+ CompareRegions (AmdExeAddrMapPtr[i], MtrrV7, &Result, StdHeader);
+ if (Result.OverlapType == EmptySet) {
+ // MTRR7 is empty. Allocate request into MTRR7.
+ MtrrV7.ExeCacheStartAddr = AmdExeAddrMapPtr[i].ExeCacheStartAddr;
+ MtrrV7.ExeCacheSize = AmdExeAddrMapPtr[i].ExeCacheSize;
+ } else if ((Result.OverlapType == Disjoint) ||
+ (Result.OverlapType == NotCombinable)) {
+ // MTRR7 is also in use and request does not overlap - error: 3rd region above 1M
+ AgesaStatus = AGESA_ERROR;
+ PutEventLog (AgesaStatus,
+ (CPU_EVENT_EXECUTION_CACHE_ALLOCATION_ERROR + AGESA_THREE_CACHE_REGIONS_ABOVE_1MB),
+ i, AmdExeAddrMapPtr[i].ExeCacheStartAddr, AmdExeAddrMapPtr[i].ExeCacheSize, 0, StdHeader);
+ break;
+ } else {
+ // Merge request with MTRR7
+ MtrrV7.ExeCacheStartAddr = Result.MergedStartAddr;
+ MtrrV7.ExeCacheSize = Result.MergedSize;
+ if (CacheInfoPtr->CarExeType == LimitedByL2Size) {
+ RemainingExecutionCacheSize += Result.OverlapAmount;
+ }
+ }
+ } else {
+ // Request overlaps with MTRR6, Merge request with MTRR6
+ MtrrV6.ExeCacheStartAddr = Result.MergedStartAddr;
+ MtrrV6.ExeCacheSize = Result.MergedSize;
+ if (CacheInfoPtr->CarExeType == LimitedByL2Size) {
+ RemainingExecutionCacheSize += Result.OverlapAmount;
+ }
+ CompareRegions (MtrrV6, MtrrV7, &Result, StdHeader);
+ if ((Result.OverlapType != Disjoint) &&
+ (Result.OverlapType != EmptySet) &&
+ (Result.OverlapType != NotCombinable)) {
+ // MTRR6 and MTRR7 now overlap, merge them into MTRR6
+ MtrrV6.ExeCacheStartAddr = Result.MergedStartAddr;
+ MtrrV6.ExeCacheSize = Result.MergedSize;
+ MtrrV7.ExeCacheStartAddr = 0;
+ MtrrV7.ExeCacheSize = 0;
+ if (CacheInfoPtr->CarExeType == LimitedByL2Size) {
+ RemainingExecutionCacheSize += Result.OverlapAmount;
+ }
+ }
+ }
+
+ // Set the VarMTRRs. Base first, then size/mask; this allows for expanding the region safely.
+ if (MtrrV6.ExeCacheSize != 0) {
+ MsrData = (UINT64) ( 0xFFFFFFFF00000000ULL | ((0xFFFFFFFFUL - (MtrrV6.ExeCacheSize - 1)) | 0x0800UL));
+ MsrData &= CacheInfoPtr->VariableMtrrMask;
+ SecondMsrData = (UINT64) ( MtrrV6.ExeCacheStartAddr | (WP_IO & 0xFULL));
+ } else {
+ MsrData = 0;
+ SecondMsrData = 0;
+ }
+ LibAmdMsrWrite (AMD_MTRR_VARIABLE_BASE6, &SecondMsrData, StdHeader);
+ LibAmdMsrWrite ((AMD_MTRR_VARIABLE_BASE6 + 1), &MsrData, StdHeader);
+
+ if (MtrrV7.ExeCacheSize != 0) {
+ MsrData = (UINT64) ( 0xFFFFFFFF00000000ULL | ((0xFFFFFFFFUL - (MtrrV7.ExeCacheSize - 1)) | 0x0800UL));
+ MsrData &= CacheInfoPtr->VariableMtrrMask;
+ SecondMsrData = (UINT64) ( MtrrV7.ExeCacheStartAddr | (WP_IO & 0xFULL));
+ } else {
+ MsrData = 0;
+ SecondMsrData = 0;
+ }
+ LibAmdMsrWrite (AMD_MTRR_VARIABLE_BASE7, &SecondMsrData, StdHeader);
+ LibAmdMsrWrite ((AMD_MTRR_VARIABLE_BASE7 + 1), &MsrData, StdHeader);
+ } // endif of MTRR region check
+ } // end of requests For loop
+
+ return AgesaStatus;
+}
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * This function calculates available L2 cache space for ROM execution.
+ *
+ * @param[in] AmdGetExeSizeParams Pointer to the start of AmdGetExeSizeParamsPtr structure
+ *
+ * @retval AGESA_SUCCESS No error
+ * @retval AGESA_ALERT No cache available for execution cache.
+ *
+ */
+AGESA_STATUS
+AmdGetAvailableExeCacheSize (
+ IN OUT AMD_GET_EXE_SIZE_PARAMS *AmdGetExeSizeParams
+ )
+{
+ UINT8 WayUsedForCar;
+ UINT8 L2Assoc;
+ UINT32 L2Size;
+ UINT32 L2WaySize;
+ UINT32 CurrentCoreNum;
+ UINT8 L2Ways;
+ UINT8 Ignored;
+ UINT32 DieNumber;
+ UINT32 TotalCores;
+ CPUID_DATA CpuIdDataStruct;
+ CACHE_INFO *CacheInfoPtr;
+ AP_MAIL_INFO ApMailboxInfo;
+ AGESA_STATUS IgnoredStatus;
+ CPU_SPECIFIC_SERVICES *FamilySpecificServices;
+
+ GetCpuServicesOfCurrentCore ((CONST CPU_SPECIFIC_SERVICES **)&FamilySpecificServices, &AmdGetExeSizeParams->StdHeader);
+ FamilySpecificServices->GetCacheInfo (FamilySpecificServices, (CONST VOID **) &CacheInfoPtr, &Ignored, &AmdGetExeSizeParams->StdHeader);
+ // CAR_EXE mode is either "Limited by L2 size" or "Infinite Execution space"
+ ASSERT (CacheInfoPtr->CarExeType < MaxCarExeMode);
+ if (CacheInfoPtr->CarExeType == InfiniteExe) {
+ AmdGetExeSizeParams->AvailableExeCacheSize = SIZE_INFINITE_EXE_CACHE;
+ return AGESA_SUCCESS;
+ }
+
+ // EXE cache size is limited by size of the L2, minus previous allocations for stack, heap, etc.
+ // Check for L2 cache size and way size
+ LibAmdCpuidRead (AMD_CPUID_L2L3Cache_L2TLB, &CpuIdDataStruct, &AmdGetExeSizeParams->StdHeader);
+ L2Assoc = (UINT8) ((CpuIdDataStruct.ECX_Reg >> 12) & 0x0F);
+
+ // get L2Ways from L2 Association to Way translation table
+ L2Ways = L2AssocToL2WayTranslationTable[L2Assoc];
+ ASSERT (L2Ways != 0xFF);
+
+ // get L2Size
+ L2Size = 1024 * ((CpuIdDataStruct.ECX_Reg >> 16) & 0xFFFF);
+
+ // get each L2WaySize
+ L2WaySize = L2Size / L2Ways;
+
+ // Determine the size for execution cache
+ if (IsBsp (&AmdGetExeSizeParams->StdHeader, &IgnoredStatus)) {
+ // BSC (Boot Strap Core)
+ WayUsedForCar = Ceiling (CacheInfoPtr->BspStackSize, L2WaySize) +
+ Ceiling (CacheInfoPtr->MemTrainingBufferSize, L2WaySize) +
+ Ceiling (AMD_HEAP_SIZE_PER_CORE , L2WaySize) +
+ Ceiling (CacheInfoPtr->SharedMemSize, L2WaySize);
+ } else {
+ // AP (Application Processor)
+ GetCurrentCore (&CurrentCoreNum, &AmdGetExeSizeParams->StdHeader);
+
+ GetApMailbox (&ApMailboxInfo.Info, &AmdGetExeSizeParams->StdHeader);
+ DieNumber = (1 << ApMailboxInfo.Fields.ModuleType);
+ GetActiveCoresInCurrentSocket (&TotalCores, &AmdGetExeSizeParams->StdHeader);
+ ASSERT ((TotalCores % DieNumber) == 0);
+ if ((CurrentCoreNum % (TotalCores / DieNumber)) == 0) {
+ WayUsedForCar = Ceiling (CacheInfoPtr->Core0StackSize , L2WaySize) +
+ Ceiling (CacheInfoPtr->MemTrainingBufferSize, L2WaySize) +
+ Ceiling (AMD_HEAP_SIZE_PER_CORE , L2WaySize) +
+ Ceiling (CacheInfoPtr->SharedMemSize, L2WaySize);
+ } else {
+ WayUsedForCar = Ceiling (CacheInfoPtr->Core1StackSize , L2WaySize) +
+ Ceiling (AMD_HEAP_SIZE_PER_CORE , L2WaySize) +
+ Ceiling (CacheInfoPtr->SharedMemSize, L2WaySize);
+ }
+ }
+
+ ASSERT (WayUsedForCar < L2Ways);
+
+ if (WayUsedForCar < L2Ways) {
+ AmdGetExeSizeParams->AvailableExeCacheSize = L2WaySize * (L2Ways - WayUsedForCar);
+ return AGESA_SUCCESS;
+ } else {
+ AmdGetExeSizeParams->AvailableExeCacheSize = 0;
+ return AGESA_ALERT;
+ }
+}
+
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * This function rounds a quotient up if the remainder is not zero.
+ *
+ * @param[in] Divisor The divisor
+ * @param[in] Dividend The dividend
+ *
+ * @retval Value Rounded quotient
+ *
+ */
+UINT8
+STATIC
+Ceiling (
+ IN UINT32 Divisor,
+ IN UINT32 Dividend
+ )
+{
+ if ((Divisor % Dividend) == 0) {
+ return (UINT8) (Divisor / Dividend);
+ } else {
+ return (UINT8) ((Divisor / Dividend) + 1);
+ }
+}
+
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * This function calculates the amount of cache that has already been allocated on the
+ * executing core.
+ *
+ * @param[in] StdHeader Handle to config for library and services
+ *
+ * @returns Allocated size in bytes
+ *
+ */
+UINT32
+STATIC
+CalculateOccupiedExeCache (
+ IN AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ UINT64 OccupExeCacheSize;
+ UINT64 MsrData;
+ UINT8 i;
+
+ MsrData = 0;
+ OccupExeCacheSize = 0;
+
+ //
+ //Calculate Variable MTRR base 6~7
+ //
+ for (i = 0; i < 2; i++) {
+ LibAmdMsrRead ((AMD_MTRR_VARIABLE_BASE6 + (2*i)), &MsrData, StdHeader);
+ if (MsrData != 0) {
+ LibAmdMsrRead ((AMD_MTRR_VARIABLE_BASE6 + (2*i + 1)), &MsrData, StdHeader);
+ OccupExeCacheSize = OccupExeCacheSize + ((~((MsrData & (0xFFFF8000)) - 1))&0xFFFF8000);
+ }
+ }
+
+ //
+ //Calculate Fixed MTRR base D0000~F8000
+ //
+ for (i = 0; i < 6; i++) {
+ LibAmdMsrRead ((AMD_MTRR_FIX4K_BASE + 2 + i), &MsrData, StdHeader);
+ if (MsrData!= 0) {
+ OccupExeCacheSize = OccupExeCacheSize + 0x8000;
+ }
+ }
+
+ return (UINT32)OccupExeCacheSize;
+}
+
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * This function compares two memory regions for overlap and returns the combined
+ * Base,Size to describe the new combined region.
+ *
+ * There are 13 cases for how two regions may overlap: key: [] region A, ** region B
+ * 1- [ ] *** 9- *** [ ] disjoint regions
+ * 2- [ ]*** 10- ***[ ] adjacent regions
+ * 3- [ ***] 11- **[**] common ending
+ * 4- [ *]** 12- *[** ] extending
+ * 5- [ ** ] 13- *[*]* contained
+ * 6- [*** ] common start, contained
+ * 7- [***] identity
+ * 8- [**]** common start, extending
+ * 0- one of the regions is empty (has base=0)
+ *
+ * @param[in] ARegion pointer to the base,size pair that describes region A
+ * @param[in] BRegion pointer to the base,size pair that describes region B
+ * @param[in,out] CRegion pointer to the base,size pair that describes region C This struct also has the
+ * overlap type and the amount of overlap between the regions.
+ * @param[in] StdHeader Handle to config for library and services
+ *
+ * @returns void, nothing
+ */
+
+VOID
+STATIC
+CompareRegions (
+ IN EXECUTION_CACHE_REGION ARegion,
+ IN EXECUTION_CACHE_REGION BRegion,
+ IN OUT MERGED_CACHE_REGION *CRegion,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ // Use Int64 to handle regions ending at or above the 4G boundary.
+ UINT64 EndOfA;
+ UINT64 EndOfB;
+
+
+ if ((BRegion.ExeCacheStartAddr == 0) ||
+ (ARegion.ExeCacheStartAddr == 0)) {
+ CRegion->MergedStartAddr =
+ CRegion->MergedSize =
+ CRegion->OverlapAmount = 0;
+ CRegion->OverlapType = EmptySet;
+ return;
+ }
+ if (BRegion.ExeCacheStartAddr < ARegion.ExeCacheStartAddr) {
+ //swap regions A & B. this collapses types 9-13 onto 1-5 and reduces the number of tests
+ CRegion->MergedStartAddr = ARegion.ExeCacheStartAddr;
+ CRegion->MergedSize = ARegion.ExeCacheSize;
+ ARegion = BRegion;
+ BRegion.ExeCacheStartAddr = CRegion->MergedStartAddr;
+ BRegion.ExeCacheSize = CRegion->MergedSize;
+ }
+ CRegion->MergedStartAddr =
+ CRegion->MergedSize =
+ CRegion->OverlapType =
+ CRegion->OverlapAmount = 0;
+
+ if (ARegion.ExeCacheStartAddr == BRegion.ExeCacheStartAddr) {
+ // Common start, cases 6,7, or 8
+ if (ARegion.ExeCacheSize == BRegion.ExeCacheSize) {
+ // case 7, identity. Need to recover the overlap size
+ CRegion->MergedStartAddr = ARegion.ExeCacheStartAddr;
+ CRegion->MergedSize = ARegion.ExeCacheSize;
+ CRegion->OverlapAmount = ARegion.ExeCacheSize;
+ CRegion->OverlapType = Identity;
+ } else if (ARegion.ExeCacheSize < BRegion.ExeCacheSize) {
+ // case 8, common start extending
+ CRegion->MergedStartAddr = ARegion.ExeCacheStartAddr;
+ CRegion->MergedSize = BRegion.ExeCacheSize;
+ CRegion->OverlapType = CommonStartExtending;
+ CRegion->OverlapAmount = ARegion.ExeCacheSize;
+ } else {
+ // case 6, common start contained
+ CRegion->MergedStartAddr = ARegion.ExeCacheStartAddr;
+ CRegion->MergedSize = ARegion.ExeCacheSize;
+ CRegion->OverlapType = CommonStartContained;
+ CRegion->OverlapAmount = BRegion.ExeCacheSize;
+ }
+ } else {
+ // A_Base is less than B_Base. check for cases 1-5
+ EndOfA = ((UINT64) ARegion.ExeCacheStartAddr) + ((UINT64) ARegion.ExeCacheSize);
+
+ if (EndOfA < ((UINT64) BRegion.ExeCacheStartAddr)) {
+ // case 1, disjoint
+ CRegion->MergedStartAddr =
+ CRegion->MergedSize =
+ CRegion->OverlapAmount = 0;
+ CRegion->OverlapType = Disjoint;
+
+ } else if (EndOfA == ((UINT64) BRegion.ExeCacheStartAddr)) {
+ // case 2, adjacent
+ CRegion->OverlapType = Adjacent;
+ CRegion->MergedStartAddr = ARegion.ExeCacheStartAddr;
+ CRegion->MergedSize = ARegion.ExeCacheSize + BRegion.ExeCacheSize;
+ CRegion->OverlapAmount = 0;
+ } else {
+ // EndOfA is > B_Base. check for cases 3,4,5
+ EndOfB = ((UINT64) BRegion.ExeCacheStartAddr) + ((UINT64) BRegion.ExeCacheSize);
+
+ if ( EndOfA < EndOfB) {
+ // case 4, extending
+ CRegion->OverlapType = Extending;
+ CRegion->MergedStartAddr = ARegion.ExeCacheStartAddr;
+ CRegion->MergedSize = (UINT32) (EndOfB - ((UINT64) ARegion.ExeCacheStartAddr));
+ CRegion->OverlapAmount = (UINT32) (EndOfA - ((UINT64) BRegion.ExeCacheStartAddr));
+ } else {
+ // case 3, same end; or case 5, contained
+ CRegion->OverlapType = Contained;
+ CRegion->MergedStartAddr = ARegion.ExeCacheStartAddr;
+ CRegion->MergedSize = ARegion.ExeCacheSize;
+ CRegion->OverlapAmount = BRegion.ExeCacheSize;
+ }
+ }
+ } // endif
+ // Once we have combined the regions, they must still obey the MTRR size and boundary rules
+ if ( CRegion->OverlapType != Disjoint ) {
+ if ((!(IsPowerOfTwo (CRegion->MergedSize))) ||
+ ((CRegion->MergedStartAddr % CRegion->MergedSize) != 0) ) {
+ CRegion->OverlapType = NotCombinable;
+ }
+ }
+
+}
+
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * This local function tests the parameter for being an even power of two
+ *
+ * @param[in] TestNumber Number to check
+ *
+ * @retval TRUE - TestNumber is a power of two,
+ * @retval FALSE - TestNumber is not a power of two
+ *
+ */
+BOOLEAN
+STATIC
+IsPowerOfTwo (
+ IN UINT32 TestNumber
+ )
+{
+ UINT32 PowerTwo;
+
+ ASSERT (TestNumber >= 0x8000UL);
+ PowerTwo = 0x8000UL; // Start at 32K
+ while ( TestNumber > PowerTwo ) {
+ PowerTwo = PowerTwo * 2;
+ }
+ return (((TestNumber % PowerTwo) == 0) ? TRUE: FALSE);
+}
+
+
diff --git a/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuCacheInit.h b/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuCacheInit.h
new file mode 100644
index 0000000000..24cc757ea7
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuCacheInit.h
@@ -0,0 +1,138 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * AMD CPU Execution Cache Allocation functions.
+ *
+ * Contains code for doing Execution Cache Allocation for ROM space
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: CPU
+ * @e \$Revision: 84150 $ @e \$Date: 2012-12-12 15:46:25 -0600 (Wed, 12 Dec 2012) $
+ *
+ */
+/*
+ ******************************************************************************
+ *
+ * Copyright (c) 2008 - 2013, Advanced Micro Devices, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Advanced Micro Devices, Inc. nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ ******************************************************************************
+ */
+
+#ifndef _CPU_CACHE_INIT_H_
+#define _CPU_CACHE_INIT_H_
+
+/*----------------------------------------------------------------------------
+ * Mixed (DEFINITIONS AND MACROS / TYPEDEFS, STRUCTURES, ENUMS)
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*-----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *-----------------------------------------------------------------------------
+ */
+#define BSP_STACK_SIZE_64K 65536
+#define BSP_STACK_SIZE_32K 32768
+
+#define CORE0_STACK_SIZE 16384
+#define CORE1_STACK_SIZE 4096
+
+#define AMD_MTRR_FIX4K_BASE 0x268
+#define AMD_MTRR_VARIABLE_BASE6 0x20C
+#define AMD_MTRR_VARIABLE_BASE7 0x20E
+
+#define WP_IO 0x0505050505050505ull
+
+#define AGESA_CACHE_SIZE_REDUCED 1
+#define AGESA_CACHE_REGIONS_ACROSS_1MB 2
+#define AGESA_CACHE_REGIONS_ACROSS_4GB 3
+#define AGESA_REGION_NOT_ALIGNED_ON_BOUNDARY 4
+#define AGESA_CACHE_START_ADDRESS_LESS_D0000 5
+#define AGESA_THREE_CACHE_REGIONS_ABOVE_1MB 6
+#define AGESA_DEALLOCATE_CACHE_REGIONS 7
+
+/*----------------------------------------------------------------------------
+ * TYPEDEFS, STRUCTURES, ENUMS
+ *
+ *----------------------------------------------------------------------------
+ */
+/// Cache-As-Ram Executable region allocation modes
+typedef enum {
+ LimitedByL2Size, ///< Execution space must be allocated from L2
+ InfiniteExe, ///< Family can support unlimited Execution space
+ MaxCarExeMode ///< Used as limit or bounds check
+} CAR_EXE_MODE;
+
+/// Cache Information
+typedef struct {
+ IN UINT32 BspStackSize; ///< Stack size of BSP
+ IN UINT32 Core0StackSize; ///< Stack size of primary cores
+ IN UINT32 Core1StackSize; ///< Stack size of all non primary cores
+ IN UINT32 MemTrainingBufferSize; ///< Memory training buffer size
+ IN UINT32 SharedMemSize; ///< Shared memory size
+ IN UINT64 VariableMtrrMask; ///< Mask to apply before variable MTRR writes
+ IN UINT64 VariableMtrrHeapMask; ///< Mask to apply before variable MTRR writes for use in heap init.
+ IN UINT64 HeapBaseMask; ///< Mask used for the heap MTRR settings
+ IN CAR_EXE_MODE CarExeType; ///< Indicates which algorithm to use when allocating EXE space
+} CACHE_INFO;
+
+/// Merged memory region overlap type
+typedef enum {
+ EmptySet, ///< One of the regions is zero length
+ Disjoint, ///< The two regions do not touch
+ Adjacent, ///< one region is next to the other, no gap
+ CommonEnd, ///< regions overlap with a common end point
+ Extending, ///< the 2nd region is extending the size of the 1st
+ Contained, ///< the 2nd region is wholely contained inside the 1st
+ CommonStartContained, ///< the 2nd region is contained in the 1st with a common start
+ Identity, ///< the two regions are the same
+ CommonStartExtending, ///< the 2nd region has same start as 1st, but is larger size
+ NotCombinable ///< the combined regions do not follow the cache block rules
+} OVERLAP_TYPE;
+
+/// Result of merging two memory regions for cache coverage
+typedef struct {
+ IN OUT UINT32 MergedStartAddr; ///< Start address of the merged regions
+ IN OUT UINT32 MergedSize; ///< Size of the merged regions
+ OUT UINT32 OverlapAmount; ///< the size of the overlapping section
+ OUT OVERLAP_TYPE OverlapType; ///< indicates how the two regions overlap
+} MERGED_CACHE_REGION;
+
+/*----------------------------------------------------------------------------
+ * FUNCTIONS PROTOTYPE
+ *
+ *----------------------------------------------------------------------------
+ */
+AGESA_STATUS
+AllocateExecutionCache (
+ IN AMD_CONFIG_PARAMS *StdHeader,
+ IN EXECUTION_CACHE_REGION *AmdExeAddrMapPtr
+ );
+
+#endif // _CPU_CACHE_INIT_H_
+
diff --git a/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuCdit.c b/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuCdit.c
new file mode 100644
index 0000000000..e02e8706c2
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuCdit.c
@@ -0,0 +1,347 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * AMD CDIT, ACPI table related API functions.
+ *
+ * Contains code that generates the CDIT table
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: CPU
+ * @e \$Revision: 84150 $ @e \$Date: 2012-12-12 15:46:25 -0600 (Wed, 12 Dec 2012) $
+ *
+ */
+/*
+ ******************************************************************************
+ *
+ * Copyright (c) 2008 - 2013, Advanced Micro Devices, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Advanced Micro Devices, Inc. nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ ******************************************************************************
+ */
+
+/*----------------------------------------------------------------------------
+ * This file provides functions, that will generate SLIT tables
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------------------
+ * M O D U L E S U S E D
+ *----------------------------------------------------------------------------------------
+ */
+
+#include "AGESA.h"
+#include "amdlib.h"
+#include "OptionCdit.h"
+#include "heapManager.h"
+#include "cpuLateInit.h"
+#include "cpuRegisters.h"
+#include "Ids.h"
+#include "cpuFeatures.h"
+#include "cpuFamilyTranslation.h"
+#include "cpuL3Features.h"
+#include "Filecode.h"
+CODE_GROUP (G3_DXE)
+RDATA_GROUP (G3_DXE)
+
+#define FILECODE PROC_CPU_FEATURE_CPUCDIT_FILECODE
+/*----------------------------------------------------------------------------------------
+ * D E F I N I T I O N S A N D M A C R O S
+ *----------------------------------------------------------------------------------------
+ */
+
+extern OPTION_CDIT_CONFIGURATION OptionCditConfiguration; // global user config record
+
+STATIC ACPI_TABLE_HEADER ROMDATA CpuCditHdrStruct =
+{
+ {'C','D','I','T'},
+ 0,
+ 1,
+ 0,
+ {0},
+ {0},
+ 1,
+ {'A','M','D',' '},
+ 1
+};
+
+/*----------------------------------------------------------------------------------------
+ * T Y P E D E F S A N D S T R U C T U R E S
+ *----------------------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------------------
+ * P R O T O T Y P E S O F L O C A L F U N C T I O N S
+ *----------------------------------------------------------------------------------------
+ */
+VOID
+STATIC
+AcpiCditHBufferFind (
+ IN OUT AMD_CONFIG_PARAMS *StdHeader,
+ IN UINT8 **SocketTopologyPtr
+ );
+
+/*----------------------------------------------------------------------------------------
+ * P R O T O T Y P E S O F E X P O R T E D F U N C T I O N S
+ *----------------------------------------------------------------------------------------
+ */
+AGESA_STATUS
+GetAcpiCditStub (
+ IN OUT AMD_CONFIG_PARAMS *StdHeader,
+ IN PLATFORM_CONFIGURATION *PlatformConfig,
+ OUT VOID **CditPtr
+ );
+
+AGESA_STATUS
+GetAcpiCditMain (
+ IN OUT AMD_CONFIG_PARAMS *StdHeader,
+ IN PLATFORM_CONFIGURATION *PlatformConfig,
+ OUT VOID **CditPtr
+ );
+
+/*----------------------------------------------------------------------------------------
+ * E X P O R T E D F U N C T I O N S
+ *----------------------------------------------------------------------------------------
+ */
+
+extern CPU_FAMILY_SUPPORT_TABLE L3FeatureFamilyServiceTable;
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ *
+ * This function generates a complete CDIT table into a memory buffer.
+ * After completion, this table must be set by the system BIOS into its
+ * internal ACPI namespace, and linked into the RSDT/XSDT
+ *
+ * @param[in, out] StdHeader Standard Head Pointer
+ * @param[in] PlatformConfig Config handle for platform specific information
+ * @param[out] CditPtr Point to Cdit Struct including buffer address and length
+ *
+ * @retval UINT32 AGESA_STATUS
+ */
+AGESA_STATUS
+CreateAcpiCdit (
+ IN OUT AMD_CONFIG_PARAMS *StdHeader,
+ IN PLATFORM_CONFIGURATION *PlatformConfig,
+ OUT VOID **CditPtr
+ )
+{
+ AGESA_TESTPOINT (TpProcCpuEntryCdit, StdHeader);
+ return ((*(OptionCditConfiguration.CditFeature)) (StdHeader, PlatformConfig, CditPtr));
+}
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ *
+ * This is the default routine for use when the CDIT option is NOT requested.
+ *
+ * The option install process will create and fill the transfer vector with
+ * the address of the proper routine (Main or Stub). The link optimizer will
+ * strip out of the .DLL the routine that is not used.
+ *
+ * @param[in, out] StdHeader Standard Head Pointer
+ * @param[in] PlatformConfig Config handle for platform specific information
+ * @param[out] CditPtr Point to Cdit Struct including buffer address and length
+ *
+ * @retval AGESA_STATUS
+ */
+
+AGESA_STATUS
+GetAcpiCditStub (
+ IN OUT AMD_CONFIG_PARAMS *StdHeader,
+ IN PLATFORM_CONFIGURATION *PlatformConfig,
+ OUT VOID **CditPtr
+ )
+{
+ return AGESA_UNSUPPORTED;
+}
+/*---------------------------------------------------------------------------------------*/
+/**
+ *
+ * This function generates a complete CDIT table into a memory buffer.
+ * After completion, this table must be set by the system BIOS into its
+ * internal ACPI namespace, and linked into the RSDT/XSDT
+ *
+ * @param[in, out] StdHeader Standard Head Pointer
+ * @param[in] PlatformConfig Config handle for platform specific information
+ * @param[out] CditPtr Point to Cdit Struct including buffer address and length
+ *
+ * @retval UINT32 AGESA_STATUS
+ */
+AGESA_STATUS
+GetAcpiCditMain (
+ IN OUT AMD_CONFIG_PARAMS *StdHeader,
+ IN PLATFORM_CONFIGURATION *PlatformConfig,
+ OUT VOID **CditPtr
+ )
+{
+ UINT8 MaxHops;
+ UINT8 DomainNum;
+ UINT8 i;
+ UINT8 j;
+ UINT8 *BufferPtr;
+ UINT8 *SocketTopologyDataPtr;
+ UINT8 *SocketTopologyPtr;
+ UINT32 Socket;
+ BOOLEAN IsProbeFilterEnabled;
+ ACPI_TABLE_HEADER *CpuCditHeaderStructPtr;
+ AGESA_STATUS Flag;
+ ALLOCATE_HEAP_PARAMS AllocStruct;
+ L3_FEATURE_FAMILY_SERVICES *FamilyServices;
+
+ MaxHops = 0;
+ SocketTopologyPtr = NULL;
+ Flag = AGESA_ERROR;
+ IsProbeFilterEnabled = FALSE;
+
+ // find out the pointer to the BufferHandle which contains
+ // Node Topology information
+ AcpiCditHBufferFind (StdHeader, &SocketTopologyPtr);
+ if (SocketTopologyPtr == NULL) {
+ return (Flag);
+ }
+
+ DomainNum = *SocketTopologyPtr;
+
+ IDS_HDT_CONSOLE (CPU_TRACE, " CDIT is created\n");
+
+ // create a buffer by calling IBV callout routine
+ AllocStruct.RequestedBufferSize = (DomainNum * DomainNum) + AMD_ACPI_CDIT_NUM_DOMAINS_LENGTH + sizeof (ACPI_TABLE_HEADER);
+ AllocStruct.BufferHandle = AMD_ACPI_CDIT_BUFFER_HANDLE;
+ AllocStruct.Persist = HEAP_SYSTEM_MEM;
+ if (HeapAllocateBuffer (&AllocStruct, StdHeader) != AGESA_SUCCESS) {
+ return (Flag);
+ }
+ *CditPtr = AllocStruct.BufferPtr;
+
+ //CDIT header
+ LibAmdMemCopy (*CditPtr, (VOID *) &CpuCditHdrStruct, (UINTN) (sizeof (ACPI_TABLE_HEADER)), StdHeader);
+ CpuCditHeaderStructPtr = (ACPI_TABLE_HEADER *) *CditPtr;
+ CpuCditHeaderStructPtr->TableLength = (UINT32) AllocStruct.RequestedBufferSize;
+ // Update table OEM fields.
+ LibAmdMemCopy ((VOID *) &CpuCditHeaderStructPtr->OemId, (VOID *) &OptionCditConfiguration.OemIdString,
+ sizeof (OptionCditConfiguration.OemIdString), StdHeader);
+ LibAmdMemCopy ((VOID *) &CpuCditHeaderStructPtr->OemTableId, (VOID *) &OptionCditConfiguration.OemTableIdString,
+ sizeof (OptionCditConfiguration.OemTableIdString), StdHeader);
+ BufferPtr = *CditPtr;
+
+ Flag = AGESA_SUCCESS;
+ // CDIT body
+ // Check if Probe Filter is enabled
+ if (IsFeatureEnabled (L3Features, PlatformConfig, StdHeader)) {
+ IsProbeFilterEnabled = TRUE;
+ for (Socket = 0; Socket < GetPlatformNumberOfSockets (); Socket++) {
+ if (IsProcessorPresent (Socket, StdHeader)) {
+ GetFeatureServicesOfSocket (&L3FeatureFamilyServiceTable, Socket, (CONST VOID **)&FamilyServices, StdHeader);
+ if ((FamilyServices == NULL) || (!FamilyServices->IsHtAssistSupported (FamilyServices, PlatformConfig, StdHeader))) {
+ IsProbeFilterEnabled = FALSE;
+ break;
+ }
+ }
+ }
+ }
+
+
+ if (!IsProbeFilterEnabled) {
+ // probe filter is disabled
+ // get MaxHops
+ SocketTopologyDataPtr = SocketTopologyPtr + sizeof (DomainNum);
+ for (i = 0; i < DomainNum; i++) {
+ for (j = 0; j < DomainNum; j++) {
+ if (*SocketTopologyDataPtr > MaxHops) {
+ MaxHops = *SocketTopologyDataPtr;
+ }
+ SocketTopologyDataPtr++;
+ }
+ }
+
+ // the Max hop entries have a value of 13
+ // and all other entries have 10.
+ SocketTopologyDataPtr = SocketTopologyPtr + sizeof (DomainNum);
+ for (i = 0; i < DomainNum; i++) {
+ for (j = 0; j < DomainNum; j++) {
+ if (*SocketTopologyDataPtr++ == MaxHops) {
+ *(BufferPtr + sizeof (ACPI_TABLE_HEADER) +
+ AMD_ACPI_CDIT_NUM_DOMAINS_LENGTH + (i * DomainNum) + j) = 13;
+ } else {
+ *(BufferPtr + sizeof (ACPI_TABLE_HEADER) +
+ AMD_ACPI_CDIT_NUM_DOMAINS_LENGTH + (i * DomainNum) + j) = 10;
+ }
+ }
+ }
+ } else {
+ // probe filter is enabled
+ // formula : num_hops * 6 + 10
+ SocketTopologyDataPtr = SocketTopologyPtr + sizeof (DomainNum);
+ for (i = 0; i < DomainNum; i++) {
+ for (j = 0; j < DomainNum; j++) {
+ *(BufferPtr + sizeof (ACPI_TABLE_HEADER) +
+ AMD_ACPI_CDIT_NUM_DOMAINS_LENGTH + (i * DomainNum) + j) =
+ ((*SocketTopologyDataPtr++) * 6) + 10;
+ }
+ }
+ }
+
+ BufferPtr += sizeof (ACPI_TABLE_HEADER);
+ *((UINT32 *) BufferPtr) = (UINT32) DomainNum;
+
+ //Update CDIT header Checksum
+ ChecksumAcpiTable ((ACPI_TABLE_HEADER *) *CditPtr, StdHeader);
+
+ return (Flag);
+}
+
+/*---------------------------------------------------------------------------------------
+ * L O C A L F U N C T I O N S
+ *---------------------------------------------------------------------------------------
+ */
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ *
+ * Find out the pointer to the BufferHandle which contains
+ * Node Topology information
+ *
+ * @param[in, out] StdHeader Standard Head Pointer
+ * @param[in] SocketTopologyPtr Point to the address of Socket Topology
+ *
+ */
+VOID
+STATIC
+AcpiCditHBufferFind (
+ IN OUT AMD_CONFIG_PARAMS *StdHeader,
+ IN UINT8 **SocketTopologyPtr
+ )
+{
+ LOCATE_HEAP_PTR LocateBuffer;
+
+ LocateBuffer.BufferHandle = HOP_COUNT_TABLE_HANDLE;
+ if (HeapLocateBuffer (&LocateBuffer, StdHeader) == AGESA_SUCCESS) {
+ *SocketTopologyPtr = (UINT8 *) LocateBuffer.BufferPtr;
+ }
+
+ return;
+}
+
diff --git a/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuCoreLeveling.c b/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuCoreLeveling.c
new file mode 100644
index 0000000000..b00e97953d
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuCoreLeveling.c
@@ -0,0 +1,374 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * AMD CPU Core Leveling Function.
+ *
+ * Contains code to Level the number of core in a multi-socket system
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: CPU
+ * @e \$Revision: 84150 $ @e \$Date: 2012-12-12 15:46:25 -0600 (Wed, 12 Dec 2012) $
+ *
+ */
+/*
+ ******************************************************************************
+ *
+ * Copyright (c) 2008 - 2013, Advanced Micro Devices, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Advanced Micro Devices, Inc. nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ ******************************************************************************
+ *----------------------------------------------------------------------------
+ */
+
+
+/*
+ *----------------------------------------------------------------------------
+ * MODULES USED
+ *
+ *----------------------------------------------------------------------------
+ */
+#include "AGESA.h"
+#include "AMD.h"
+#include "Topology.h"
+#include "cpuRegisters.h"
+#include "GeneralServices.h"
+#include "cpuServices.h"
+#include "cpuFamilyTranslation.h"
+#include "cpuFeatures.h"
+#include "cpuEarlyInit.h"
+#include "Filecode.h"
+CODE_GROUP (G1_PEICC)
+RDATA_GROUP (G1_PEICC)
+#define FILECODE PROC_CPU_FEATURE_CPUCORELEVELING_FILECODE
+/*----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+
+/*----------------------------------------------------------------------------
+ * TYPEDEFS AND STRUCTURES
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------------------
+ * E X P O R T E D F U N C T I O N S
+ *----------------------------------------------------------------------------------------
+ */
+extern CPU_FAMILY_SUPPORT_TABLE CoreLevelingFamilyServiceTable;
+
+/*----------------------------------------------------------------------------
+ * PROTOTYPES OF LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+AGESA_STATUS
+CoreLevelingAtEarly (
+ IN UINT64 EntryPoint,
+ IN PLATFORM_CONFIGURATION *PlatformConfig,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ );
+
+/*----------------------------------------------------------------------------------------
+ * P U B L I C F U N C T I O N S
+ *----------------------------------------------------------------------------------------
+ */
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * Should core leveling be enabled
+ *
+ * @param[in] PlatformConfig Contains the runtime modifiable feature input data.
+ * @param[in] StdHeader Config Handle for library, services.
+ *
+ * @retval TRUE core leveling is supported.
+ * @retval FALSE core leveling cannot be enabled.
+ *
+ */
+BOOLEAN
+STATIC
+IsCoreLevelingEnabled (
+ IN PLATFORM_CONFIGURATION *PlatformConfig,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ CORE_LEVELING_TYPE CoreLevelMode;
+
+ CoreLevelMode = (CORE_LEVELING_TYPE) PlatformConfig->CoreLevelingMode;
+ if (CoreLevelMode != CORE_LEVEL_NONE) {
+ return (TRUE);
+ } else {
+ return (FALSE);
+ }
+}
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * Performs core leveling for the system.
+ *
+ * This function implements the AMD_CPU_EARLY_PARAMS.CoreLevelingMode parameter.
+ * The possible modes are:
+ * -0 CORE_LEVEL_LOWEST Level to lowest common denominator
+ * -1 CORE_LEVEL_TWO Level to 2 cores
+ * -2 CORE_LEVEL_POWER_OF_TWO Level to 1,2,4 or 8
+ * -3 CORE_LEVEL_NONE Do no leveling
+ * -4 CORE_LEVEL_COMPUTE_UNIT Level cores to one core per compute unit
+ *
+ * @param[in] EntryPoint Timepoint designator.
+ * @param[in] PlatformConfig Contains the leveling mode parameter
+ * @param[in] StdHeader Config handle for library and services
+ *
+ * @return The most severe status of any family specific service.
+ *
+ */
+AGESA_STATUS
+CoreLevelingAtEarly (
+ IN UINT64 EntryPoint,
+ IN PLATFORM_CONFIGURATION *PlatformConfig,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ UINT32 CoreNumPerComputeUnit;
+ UINT32 MinNumOfComputeUnit;
+ UINT32 EnabledComputeUnit;
+ UINT32 Socket;
+ UINT32 Module;
+ UINT32 NumberOfSockets;
+ UINT32 NumberOfModules;
+ UINT32 MinCoreCountOnNode;
+ UINT32 MaxCoreCountOnNode;
+ UINT32 LowCore;
+ UINT32 HighCore;
+ UINT32 LeveledCores;
+ UINT32 RequestedCores;
+ UINT32 TotalEnabledCoresOnNode;
+ BOOLEAN RegUpdated;
+ AP_MAIL_INFO ApMailboxInfo;
+ CORE_LEVELING_TYPE CoreLevelMode;
+ CPU_CORE_LEVELING_FAMILY_SERVICES *FamilySpecificServices;
+ WARM_RESET_REQUEST Request;
+
+ IDS_HDT_CONSOLE (CPU_TRACE, "CoreLevelingAtEarly\n CoreLevelMode: %d\n", PlatformConfig->CoreLevelingMode);
+
+ MaxCoreCountOnNode = 0;
+ MinCoreCountOnNode = 0xFFFFFFFF;
+ LeveledCores = 0;
+ CoreNumPerComputeUnit = 1;
+ MinNumOfComputeUnit = 0xFF;
+
+ ASSERT (PlatformConfig->CoreLevelingMode < CoreLevelModeMax);
+
+ // Get OEM IO core level mode
+ CoreLevelMode = (CORE_LEVELING_TYPE) PlatformConfig->CoreLevelingMode;
+
+ // Get socket count
+ NumberOfSockets = GetPlatformNumberOfSockets ();
+ GetApMailbox (&ApMailboxInfo.Info, StdHeader);
+ NumberOfModules = ApMailboxInfo.Fields.ModuleType + 1;
+
+ // Collect cpu core info
+ for (Socket = 0; Socket < NumberOfSockets; Socket++) {
+ if (IsProcessorPresent (Socket, StdHeader)) {
+ for (Module = 0; Module < NumberOfModules; Module++) {
+ if (GetGivenModuleCoreRange (Socket, Module, &LowCore, &HighCore, StdHeader)) {
+ // Get the highest and lowest core count in all nodes
+ TotalEnabledCoresOnNode = HighCore - LowCore + 1;
+ if (TotalEnabledCoresOnNode < MinCoreCountOnNode) {
+ MinCoreCountOnNode = TotalEnabledCoresOnNode;
+ }
+ if (TotalEnabledCoresOnNode > MaxCoreCountOnNode) {
+ MaxCoreCountOnNode = TotalEnabledCoresOnNode;
+ }
+ EnabledComputeUnit = TotalEnabledCoresOnNode;
+ switch (GetComputeUnitMapping (StdHeader)) {
+ case AllCoresMapping:
+ // All cores are in their own compute unit.
+ break;
+ case EvenCoresMapping:
+ // Cores are paired in compute units.
+ CoreNumPerComputeUnit = 2;
+ EnabledComputeUnit = (TotalEnabledCoresOnNode / 2);
+ break;
+ case TripleCoresMapping:
+ // Three cores are grouped in compute units.
+ CoreNumPerComputeUnit = 3;
+ EnabledComputeUnit = (TotalEnabledCoresOnNode / 3);
+ break;
+ case QuadCoresMapping:
+ // Four cores are grouped in compute units.
+ CoreNumPerComputeUnit = 4;
+ EnabledComputeUnit = (TotalEnabledCoresOnNode / 4);
+ break;
+ default:
+ ASSERT (FALSE);
+ }
+ // Get minimum of compute unit. This will either be the minimum number of cores (AllCoresMapping),
+ // or less (EvenCoresMapping).
+ if (EnabledComputeUnit < MinNumOfComputeUnit) {
+ MinNumOfComputeUnit = EnabledComputeUnit;
+ }
+ IDS_HDT_CONSOLE (CPU_TRACE, " Socket %d Module %d MaxCoreCountOnNode %d MinCoreCountOnNode %d TotalEnabledCoresOnNode %d EnabledComputeUnit %d MinNumOfComputeUnit %d\n", \
+ Socket, Module, MaxCoreCountOnNode, MinCoreCountOnNode, TotalEnabledCoresOnNode, EnabledComputeUnit, MinNumOfComputeUnit);
+ }
+ }
+ }
+ }
+
+ // Get LeveledCores
+ switch (CoreLevelMode) {
+ case CORE_LEVEL_LOWEST:
+ if (MinCoreCountOnNode == MaxCoreCountOnNode) {
+ return (AGESA_SUCCESS);
+ }
+ LeveledCores = (MinCoreCountOnNode / CoreNumPerComputeUnit) * CoreNumPerComputeUnit;
+ break;
+ case CORE_LEVEL_TWO:
+ LeveledCores = 2 / NumberOfModules;
+ if (LeveledCores != 0) {
+ LeveledCores = (LeveledCores <= MinCoreCountOnNode) ? LeveledCores : MinCoreCountOnNode;
+ } else {
+ return (AGESA_WARNING);
+ }
+ if ((LeveledCores * NumberOfModules) != 2) {
+ PutEventLog (
+ AGESA_WARNING,
+ CPU_WARNING_ADJUSTED_LEVELING_MODE,
+ 2, (LeveledCores * NumberOfModules), 0, 0, StdHeader
+ );
+ }
+ break;
+ case CORE_LEVEL_POWER_OF_TWO:
+ // Level to power of 2 (1, 2, 4, 8...)
+ LeveledCores = 1;
+ while (MinCoreCountOnNode >= (LeveledCores * 2)) {
+ LeveledCores = LeveledCores * 2;
+ }
+ break;
+ case CORE_LEVEL_COMPUTE_UNIT:
+ case CORE_LEVEL_COMPUTE_UNIT_TWO:
+ case CORE_LEVEL_COMPUTE_UNIT_THREE:
+ // Level cores to 1~3 core(s) per compute unit, with additional reduction to level
+ // all processors to match the processor with the minimum number of cores.
+ if (CoreNumPerComputeUnit == 1) {
+ // If there is one core per compute unit, this is the same as CORE_LEVEL_LOWEST.
+ if (MinCoreCountOnNode == MaxCoreCountOnNode) {
+ return (AGESA_SUCCESS);
+ }
+ LeveledCores = MinCoreCountOnNode;
+ } else {
+ // If there are more than one core per compute unit, level to the number of compute units * cores per compute unit.
+ LeveledCores = MinNumOfComputeUnit * (CoreLevelMode - CORE_LEVEL_COMPUTE_UNIT + 1);
+ }
+ break;
+ case CORE_LEVEL_ONE:
+ LeveledCores = 1;
+ if (NumberOfModules > 1) {
+ PutEventLog (
+ AGESA_WARNING,
+ CPU_WARNING_ADJUSTED_LEVELING_MODE,
+ 1, NumberOfModules, 0, 0, StdHeader
+ );
+ }
+ break;
+ case CORE_LEVEL_THREE:
+ case CORE_LEVEL_FOUR:
+ case CORE_LEVEL_FIVE:
+ case CORE_LEVEL_SIX:
+ case CORE_LEVEL_SEVEN:
+ case CORE_LEVEL_EIGHT:
+ case CORE_LEVEL_NINE:
+ case CORE_LEVEL_TEN:
+ case CORE_LEVEL_ELEVEN:
+ case CORE_LEVEL_TWELVE:
+ case CORE_LEVEL_THIRTEEN:
+ case CORE_LEVEL_FOURTEEN:
+ case CORE_LEVEL_FIFTEEN:
+ // MCM processors can not have an odd number of cores. For an odd CORE_LEVEL_N, MCM processors will be
+ // leveled as though CORE_LEVEL_N+1 was chosen.
+ // Processors with compute units disable all cores in an entire compute unit at a time, or on an MCM processor,
+ // two compute units at a time. For example, on an SCM processor with two cores per compute unit, the effective
+ // explicit levels are CORE_LEVEL_ONE, CORE_LEVEL_TWO, CORE_LEVEL_FOUR, CORE_LEVEL_SIX, and
+ // CORE_LEVEL_EIGHT. The same example for an MCM processor with two cores per compute unit has effective
+ // explicit levels of CORE_LEVEL_TWO, CORE_LEVEL_FOUR, CORE_LEVEL_EIGHT, and CORE_LEVEL_TWELVE.
+ RequestedCores = CoreLevelMode - CORE_LEVEL_THREE + 3;
+ LeveledCores = (RequestedCores + NumberOfModules - 1) / NumberOfModules;
+ LeveledCores = (LeveledCores / CoreNumPerComputeUnit) * CoreNumPerComputeUnit;
+ LeveledCores = (LeveledCores <= MinCoreCountOnNode) ? LeveledCores : MinCoreCountOnNode;
+ if (LeveledCores != 1) {
+ LeveledCores = (LeveledCores / CoreNumPerComputeUnit) * CoreNumPerComputeUnit;
+ }
+ if ((LeveledCores * NumberOfModules * CoreNumPerComputeUnit) != RequestedCores) {
+ PutEventLog (
+ AGESA_WARNING,
+ CPU_WARNING_ADJUSTED_LEVELING_MODE,
+ RequestedCores, (LeveledCores * NumberOfModules * CoreNumPerComputeUnit), 0, 0, StdHeader
+ );
+ }
+ break;
+ default:
+ ASSERT (FALSE);
+ }
+
+ // Set down core register
+ for (Socket = 0; Socket < NumberOfSockets; Socket++) {
+ if (IsProcessorPresent (Socket, StdHeader)) {
+ GetFeatureServicesOfSocket (&CoreLevelingFamilyServiceTable, Socket, (CONST VOID **)&FamilySpecificServices, StdHeader);
+ if (FamilySpecificServices != NULL) {
+ for (Module = 0; Module < NumberOfModules; Module++) {
+ IDS_HDT_CONSOLE (CPU_TRACE, " SetDownCoreRegister: Socket %d Module %d LeveledCores %d CoreLevelMode %d\n", Socket, Module, LeveledCores, CoreLevelMode);
+ RegUpdated = FamilySpecificServices->SetDownCoreRegister (FamilySpecificServices, &Socket, &Module, &LeveledCores, CoreLevelMode, StdHeader);
+ // If the down core register is updated, trigger a warm reset.
+ if (RegUpdated) {
+ GetWarmResetFlag (StdHeader, &Request);
+ Request.RequestBit = TRUE;
+ Request.StateBits = Request.PostStage - 1;
+ IDS_HDT_CONSOLE (CPU_TRACE, " Request a warm reset.\n");
+ SetWarmResetFlag (StdHeader, &Request);
+ }
+ }
+ }
+ }
+ }
+
+ return (AGESA_SUCCESS);
+}
+
+
+CONST CPU_FEATURE_DESCRIPTOR ROMDATA CpuFeatureCoreLeveling =
+{
+ CoreLeveling,
+ (CPU_FEAT_AFTER_PM_INIT),
+ IsCoreLevelingEnabled,
+ CoreLevelingAtEarly
+};
+
+/*----------------------------------------------------------------------------------------
+ * L O C A L F U N C T I O N S
+ *----------------------------------------------------------------------------------------
+ */
+
diff --git a/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuCpb.c b/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuCpb.c
new file mode 100644
index 0000000000..0745452755
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuCpb.c
@@ -0,0 +1,175 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * AMD AGESA CPU Core performance boost feature support code.
+ *
+ * Contains code that declares the AGESA CPU CPB related APIs
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: CPU/Feature
+ * @e \$Revision: 84150 $ @e \$Date: 2012-12-12 15:46:25 -0600 (Wed, 12 Dec 2012) $
+ *
+ */
+/*
+ ******************************************************************************
+ *
+ * Copyright (c) 2008 - 2013, Advanced Micro Devices, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Advanced Micro Devices, Inc. nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ ******************************************************************************
+ */
+
+/*----------------------------------------------------------------------------------------
+ * M O D U L E S U S E D
+ *----------------------------------------------------------------------------------------
+ */
+#include "AGESA.h"
+#include "cpuFamilyTranslation.h"
+#include "cpuFeatures.h"
+#include "cpuCpb.h"
+#include "Filecode.h"
+CODE_GROUP (G1_PEICC)
+RDATA_GROUP (G1_PEICC)
+
+#define FILECODE PROC_CPU_FEATURE_CPUCPB_FILECODE
+
+/*----------------------------------------------------------------------------------------
+ * D E F I N I T I O N S A N D M A C R O S
+ *----------------------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------------------
+ * T Y P E D E F S A N D S T R U C T U R E S
+ *----------------------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------------------
+ * P R O T O T Y P E S O F L O C A L F U N C T I O N S
+ *----------------------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------------------
+ * E X P O R T E D F U N C T I O N S
+ *----------------------------------------------------------------------------------------
+ */
+extern CPU_FAMILY_SUPPORT_TABLE CpbFamilyServiceTable;
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * Should CPB be enabled
+ *
+ * @param[in] PlatformConfig Contains the runtime modifiable feature input data.
+ * @param[in] StdHeader Config Handle for library, services.
+ *
+ * @retval TRUE CPB is supported.
+ * @retval FALSE CPB cannot be enabled.
+ *
+ */
+BOOLEAN
+STATIC
+IsCpbFeatureEnabled (
+ IN PLATFORM_CONFIGURATION *PlatformConfig,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ UINT32 Socket;
+ BOOLEAN IsEnabled;
+ CPB_FAMILY_SERVICES *FamilyServices;
+
+ IsEnabled = FALSE;
+
+ ASSERT (PlatformConfig->CpbMode < MaxCpbMode);
+
+ if (PlatformConfig->CpbMode == CpbModeAuto) {
+ for (Socket = 0; Socket < GetPlatformNumberOfSockets (); Socket++) {
+ if (IsProcessorPresent (Socket, StdHeader)) {
+ GetFeatureServicesOfSocket (&CpbFamilyServiceTable, Socket, (CONST VOID **)&FamilyServices, StdHeader);
+ if (FamilyServices != NULL) {
+ if (FamilyServices->IsCpbSupported (FamilyServices, PlatformConfig, Socket, StdHeader)) {
+ IsEnabled = TRUE;
+ break;
+ }
+ }
+ }
+ }
+ }
+ return IsEnabled;
+}
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * Enable core performance boost
+ *
+ * @param[in] EntryPoint Timepoint designator.
+ * @param[in] PlatformConfig Contains the runtime modifiable feature input data.
+ * @param[in] StdHeader Config Handle for library, services.
+ *
+ * @retval AGESA_SUCCESS Always succeeds.
+ *
+ */
+AGESA_STATUS
+STATIC
+InitializeCpbFeature (
+ IN UINT64 EntryPoint,
+ IN PLATFORM_CONFIGURATION *PlatformConfig,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ UINT32 Socket;
+ AGESA_STATUS AgesaStatus;
+ AGESA_STATUS CalledStatus;
+ CPB_FAMILY_SERVICES *FamilyServices;
+
+ AgesaStatus = AGESA_SUCCESS;
+ CalledStatus = AGESA_SUCCESS;
+
+ IDS_HDT_CONSOLE (CPU_TRACE, " Boost is enabled\n");
+
+ for (Socket = 0; Socket < GetPlatformNumberOfSockets (); Socket++) {
+ if (IsProcessorPresent (Socket, StdHeader)) {
+ GetFeatureServicesOfSocket (&CpbFamilyServiceTable, Socket, (CONST VOID **)&FamilyServices, StdHeader);
+ if (FamilyServices != NULL) {
+ if (FamilyServices->IsCpbSupported (FamilyServices, PlatformConfig, Socket, StdHeader)) {
+ CalledStatus = FamilyServices->EnableCpbOnSocket (FamilyServices, PlatformConfig, EntryPoint, Socket, StdHeader);
+ if (CalledStatus > AgesaStatus) {
+ AgesaStatus = CalledStatus;
+ }
+ }
+ }
+ }
+ }
+
+ return AgesaStatus;
+}
+
+
+CONST CPU_FEATURE_DESCRIPTOR ROMDATA CpuFeatureCpb =
+{
+ CoreBoost,
+ (CPU_FEAT_AFTER_PM_INIT | CPU_FEAT_INIT_LATE_END | CPU_FEAT_AFTER_POST_MTRR_SYNC | CPU_FEAT_S3_LATE_RESTORE_END | CPU_FEAT_AFTER_RESUME_MTRR_SYNC),
+ IsCpbFeatureEnabled,
+ InitializeCpbFeature
+};
diff --git a/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuCpb.h b/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuCpb.h
new file mode 100644
index 0000000000..dd3e359fe6
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuCpb.h
@@ -0,0 +1,133 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * AMD AGESA CPU Core Performance Boost Functions declarations.
+ *
+ * Contains code that declares the AGESA CPU CPB related APIs
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: CPU/Feature
+ * @e \$Revision: 84150 $ @e \$Date: 2012-12-12 15:46:25 -0600 (Wed, 12 Dec 2012) $
+ *
+ */
+/*
+ ******************************************************************************
+ *
+ * Copyright (c) 2008 - 2013, Advanced Micro Devices, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Advanced Micro Devices, Inc. nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ ******************************************************************************
+ */
+
+#ifndef _CPU_CPB_H_
+#define _CPU_CPB_H_
+
+/*----------------------------------------------------------------------------------------
+ * M I X E D (Definitions And Macros / Typedefs, Structures, Enums)
+ *----------------------------------------------------------------------------------------
+ */
+// Forward declaration needed for multi-structure mutual references
+AGESA_FORWARD_DECLARATION (CPB_FAMILY_SERVICES);
+
+/*----------------------------------------------------------------------------------------
+ * D E F I N I T I O N S A N D M A C R O S
+ *----------------------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------------------
+ * T Y P E D E F S A N D S T R U C T U R E S
+ *----------------------------------------------------------------------------------------
+ */
+
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * Family specific call to check if CPB is supported.
+ *
+ * @param[in] CpbServices Core Performance Boost services.
+ * @param[in] PlatformConfig Contains the runtime modifiable feature input data.
+ * @param[in] Socket Zero-based socket number.
+ * @param[in] StdHeader Config Handle for library, services.
+ *
+ * @retval TRUE CPB is supported.
+ * @retval FALSE CPB is not supported.
+ *
+ */
+typedef BOOLEAN F_CPB_IS_SUPPORTED (
+ IN CPB_FAMILY_SERVICES *CpbServices,
+ IN PLATFORM_CONFIGURATION *PlatformConfig,
+ IN UINT32 Socket,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ );
+
+/// Reference to a Method.
+typedef F_CPB_IS_SUPPORTED *PF_CPB_IS_SUPPORTED;
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * Family specific call to enable CPB.
+ *
+ * @param[in] CpbServices Core Performance Boost services.
+ * @param[in] PlatformConfig Contains the runtime modifiable feature input data.
+ * @param[in] EntryPoint Timepoint designator.
+ * @param[in] Socket Zero-based socket number.
+ * @param[in] StdHeader Config Handle for library, services.
+ *
+ * @return Family specific error value.
+ *
+ */
+typedef AGESA_STATUS F_CPB_INIT (
+ IN CPB_FAMILY_SERVICES *CpbServices,
+ IN PLATFORM_CONFIGURATION *PlatformConfig,
+ IN UINT64 EntryPoint,
+ IN UINT32 Socket,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ );
+
+/// Reference to a Method.
+typedef F_CPB_INIT *PF_CPB_INIT;
+
+/**
+ * Provide the interface to the CPB Family Specific Services.
+ *
+ * Use the methods or data in this struct to adapt the feature code to a specific cpu family or model (or stepping!).
+ * Each supported Family must provide an implementation for all methods in this interface, even if the
+ * implementation is a CommonReturn().
+ */
+struct _CPB_FAMILY_SERVICES {
+ UINT16 Revision; ///< Interface version
+ // Public Methods.
+ PF_CPB_IS_SUPPORTED IsCpbSupported; ///< Method: Family specific call to check if CPB is supported.
+ PF_CPB_INIT EnableCpbOnSocket; ///< Method: Family specific call to enable CPB.
+};
+
+
+/*----------------------------------------------------------------------------------------
+ * F U N C T I O N S P R O T O T Y P E
+ *----------------------------------------------------------------------------------------
+ */
+
+#endif // _CPU_CPB_H_
diff --git a/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuCrat.c b/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuCrat.c
new file mode 100644
index 0000000000..552713d2cd
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuCrat.c
@@ -0,0 +1,513 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * AMD CRAT, ACPI table related API functions.
+ *
+ * Contains code that Create the APCI CRAT Table after early reset.
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: CPU/FEATURE
+ * @e \$Revision: 84150 $ @e \$Date: 2012-12-12 15:46:25 -0600 (Wed, 12 Dec 2012) $
+ *
+ */
+/*
+ ******************************************************************************
+ *
+ * Copyright (c) 2008 - 2013, Advanced Micro Devices, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Advanced Micro Devices, Inc. nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ ***************************************************************************/
+
+
+/*----------------------------------------------------------------------------
+ * This file provides functions, that will generate CRAT tables
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------------------
+ * M O D U L E S U S E D
+ *----------------------------------------------------------------------------------------
+ */
+#include "AGESA.h"
+#include "amdlib.h"
+#include "cpuServices.h"
+#include "OptionCrat.h"
+#include "cpuCrat.h"
+#include "mfCrat.h"
+#include "heapManager.h"
+#include "cpuRegisters.h"
+#include "cpuFamilyTranslation.h"
+#include "cpuLateInit.h"
+#include "Ids.h"
+#include "Filecode.h"
+CODE_GROUP (G3_DXE)
+RDATA_GROUP (G3_DXE)
+
+#define FILECODE PROC_CPU_FEATURE_CPUCRAT_FILECODE
+/*----------------------------------------------------------------------------------------
+ * D E F I N I T I O N S A N D M A C R O S
+ *----------------------------------------------------------------------------------------
+ */
+extern OPTION_CRAT_CONFIGURATION OptionCratConfiguration; // global user config record
+extern CPU_FAMILY_SUPPORT_TABLE CratFamilyServiceTable;
+extern S_MAKE_CRAT_ENTRY MakeCratEntryTable[];
+
+/*----------------------------------------------------------------------------------------
+ * E X P O R T E D F U N C T I O N S
+ *----------------------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------------------
+ * T Y P E D E F S A N D S T R U C T U R E S
+ *----------------------------------------------------------------------------------------
+ */
+AGESA_STATUS
+GetAcpiCratStub (
+ IN OUT AMD_CONFIG_PARAMS *StdHeader,
+ OUT VOID **CratPtr
+ );
+
+AGESA_STATUS
+GetAcpiCratMain (
+ IN OUT AMD_CONFIG_PARAMS *StdHeader,
+ OUT VOID **CratPtr
+ );
+
+/*----------------------------------------------------------------------------
+ * All of the DATA should be defined in _CODE segment.
+ * Use ROMDATA to specify that it belongs to _CODE.
+ *----------------------------------------------------------------------------
+ */
+CONST UINT8 ROMDATA L2L3Associativity[] =
+{
+ 0,
+ 1,
+ 2,
+ 0,
+ 4,
+ 0,
+ 8,
+ 0,
+ 16,
+ 0,
+ 32,
+ 48,
+ 64,
+ 96,
+ 128,
+ 0xFF
+};
+
+STATIC CRAT_HEADER ROMDATA CratHeaderStruct =
+{
+ {'C','R','A','T'},
+ 0,
+ 1,
+ 0,
+ {0},
+ {0},
+ 1,
+ {'A','M','D',' '},
+ 1,
+ 0,
+ 0,
+ {0, 0, 0, 0, 0, 0}
+};
+
+/*----------------------------------------------------------------------------------------
+ * P R O T O T Y P E S O F L O C A L F U N C T I O N S
+ *----------------------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------------------
+ * E X P O R T E D F U N C T I O N S
+ *----------------------------------------------------------------------------------------
+ */
+/*---------------------------------------------------------------------------------------*/
+/**
+ *
+ * This function will generate a complete Component Resource Affinity Table
+ * i.e. CRAT into a memory buffer. After completion, this table must be set
+ * by the system BIOS into its internal ACPI name space.
+ *
+ * @param[in, out] StdHeader Standard Head Pointer
+ * @param[out] CratPtr Point to Crat Struct including buffer address and length
+ *
+ * @retval AGESA_STATUS
+ */
+
+AGESA_STATUS
+CreateAcpiCrat (
+ IN OUT AMD_CONFIG_PARAMS *StdHeader,
+ OUT VOID **CratPtr
+ )
+{
+ AGESA_TESTPOINT (TpProcCpuEntryCrat, StdHeader);
+ return ((*(OptionCratConfiguration.CratFeature)) (StdHeader, CratPtr));
+}
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ *
+ * This is the default routine for use when the CRAT option is NOT requested.
+ *
+ * The option install process will create and fill the transfer vector with
+ * the address of the proper routine (Main or Stub). The link optimizer will
+ * strip out of the .DLL the routine that is not used.
+ *
+ * @param[in, out] StdHeader Standard Head Pointer
+ * @param[out] CratPtr Point to Crat Struct including buffer address and length
+ *
+ * @retval AGESA_STATUS
+ */
+
+AGESA_STATUS
+GetAcpiCratStub (
+ IN OUT AMD_CONFIG_PARAMS *StdHeader,
+ OUT VOID **CratPtr
+ )
+{
+ return AGESA_UNSUPPORTED;
+}
+/*---------------------------------------------------------------------------------------*/
+/**
+ *
+ * This function will generate a complete Component Resource Affinity Table
+ * i.e. CRAT into a memory buffer. After completion, this table must be set
+ * by the system BIOS into its internal ACPI name space.
+ *
+ * @param[in, out] StdHeader Standard Head Pointer
+ * @param[out] CratPtr Point to Crat Struct including buffer address and length
+ *
+ * @retval AGESA_STATUS
+ */
+AGESA_STATUS
+GetAcpiCratMain (
+ IN OUT AMD_CONFIG_PARAMS *StdHeader,
+ OUT VOID **CratPtr
+ )
+{
+ UINT8 i;
+ UINT8 *TableEnd;
+ CRAT_HEADER *CratHeaderStructPtr;
+ ALLOCATE_HEAP_PARAMS AllocParams;
+
+ // Allocate a buffer
+ AllocParams.RequestedBufferSize = CRAT_MAX_LENGTH;
+ AllocParams.BufferHandle = AMD_CRAT_INFO_BUFFER_HANDLE;
+ AllocParams.Persist = HEAP_SYSTEM_MEM;
+
+ if (HeapAllocateBuffer (&AllocParams, StdHeader) != AGESA_SUCCESS) {
+ return AGESA_ERROR;
+ }
+ *CratPtr = AllocParams.BufferPtr;
+
+
+ CratHeaderStructPtr = (CRAT_HEADER *) *CratPtr;
+ TableEnd = (UINT8 *) *CratPtr;
+
+ // Copy CratHeaderStruct -> data buffer
+ LibAmdMemCopy ((VOID *) CratHeaderStructPtr, (VOID *) &CratHeaderStruct, (UINTN) (sizeof (CRAT_HEADER)), StdHeader);
+ // Update table OEM fields.
+ LibAmdMemCopy ((VOID *) &CratHeaderStructPtr->OemId, (VOID *) &OptionCratConfiguration.OemIdString,
+ sizeof (OptionCratConfiguration.OemIdString), StdHeader);
+ LibAmdMemCopy ((VOID *) &CratHeaderStructPtr->OemTableId, (VOID *) &OptionCratConfiguration.OemTableIdString,
+ sizeof (OptionCratConfiguration.OemTableIdString), StdHeader);
+
+ TableEnd += sizeof (CRAT_HEADER);
+
+ // Make all CRAT entries.
+ for (i = 0; MakeCratEntryTable[i].MakeCratEntry != NULL; i++) {
+ MakeCratEntryTable[i].MakeCratEntry (CratHeaderStructPtr, &TableEnd, StdHeader);
+
+ }
+
+ // Store size in table (current buffer offset - buffer start offset)
+ CratHeaderStructPtr->Length = (UINT32) (TableEnd - (UINT8 *) CratHeaderStructPtr);
+
+ //Update SSDT header Checksum
+ ChecksumAcpiTable ((ACPI_TABLE_HEADER *) CratHeaderStructPtr, StdHeader);
+ IDS_HDT_CONSOLE (CPU_TRACE, " CRAT is created\n");
+ return AGESA_SUCCESS;
+}
+
+
+/*----------------------------------------------------------------------------------------
+ * L O C A L F U N C T I O N S
+ *----------------------------------------------------------------------------------------
+ */
+
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * This function will add HSA Processing Unit entry.
+ *
+ * @param[in] CratHeaderStructPtr CRAT header pointer
+ * @param[in, out] TableEnd The end of CRAT
+ * @param[in, out] StdHeader Standard Head Pointer
+ *
+ */
+VOID
+MakeHSAProcUnitEntry (
+ IN CRAT_HEADER *CratHeaderStructPtr,
+ IN OUT UINT8 **TableEnd,
+ IN OUT AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ UINT8 NodeNum;
+ UINT8 NodeCount;
+ UINT32 Socket;
+ UINT32 Module;
+ UINT32 LowCore;
+ UINT32 HighCore;
+ UINT32 RegVal;
+ CRAT_HSA_PROCESSING_UNIT *EntryPtr;
+ AMD_APIC_PARAMS ApicParams;
+ PCI_ADDR PciAddress;
+
+ // Get Node count
+ PciAddress.AddressValue = MAKE_SBDFO (0, 0, LOW_NODE_DEVICEID, FUNC_0, 0x60);
+ LibAmdPciRead (AccessWidth32 , PciAddress, &RegVal, StdHeader);
+ NodeCount = (UINT8) (((RegVal >> 4) & 0x7) + 1);
+
+ NodeNum = 0;
+ ApicParams.StdHeader = *StdHeader;
+ while (NodeNum < NodeCount) {
+ GetSocketModuleOfNode ((UINT32) NodeNum, &Socket, &Module, StdHeader);
+ GetGivenModuleCoreRange (Socket, Module, &LowCore, &HighCore, StdHeader);
+ ApicParams.Socket = (UINT8) Socket;
+ ApicParams.Core = 0;
+ AmdGetApicId (&ApicParams);
+ if (ApicParams.IsPresent) {
+ // Adding one CRAT entry for every node
+ EntryPtr = (CRAT_HSA_PROCESSING_UNIT *) AddOneCratEntry (CRAT_TYPE_HSA_PROC_UNIT, CratHeaderStructPtr, TableEnd, StdHeader);
+
+ EntryPtr->ProximityDomain = NodeNum;
+ EntryPtr->ProcessorIdLow = ApicParams.ApicAddress;
+ EntryPtr->NumCPUCores = (UINT16) (HighCore - LowCore + 1);
+ EntryPtr->Flags.Enabled = 1;
+ EntryPtr->Flags.CpuPresent = 1;
+ }
+ /// @todo SimdCount SimdWidth IoCount
+ CratHeaderStructPtr->NumDomains++;
+ NodeNum++;
+ }
+}
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * This function will add memory entry.
+ *
+ * @param[in] CratHeaderStructPtr CRAT header pointer
+ * @param[in, out] TableEnd The end of CRAT
+ * @param[in, out] StdHeader Standard Head Pointer
+ *
+ */
+VOID
+MakeMemoryEntry (
+ IN CRAT_HEADER *CratHeaderStructPtr,
+ IN OUT UINT8 **TableEnd,
+ IN OUT AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ UINT8 EntryNum;
+ UINT8 NumOfMemAffinityInfoEntries;
+ UINT32 Width;
+ AGESA_STATUS AgesaStatus;
+ CRAT_MEMORY *EntryPtr;
+ LOCATE_HEAP_PTR LocateHeapParams;
+ CRAT_MEMORY_AFFINITY_INFO_HEADER *MemAffinityInfoHeaderPtr;
+ CRAT_MEMORY_AFFINITY_INFO_ENTRY *MemAffinityInfoEntryPtr;
+
+ EntryNum = 0;
+
+ // Get the CRAT memory affinity info from heap
+ LocateHeapParams.BufferHandle = AMD_MEM_CRAT_INFO_BUFFER_HANDLE;
+ AgesaStatus = HeapLocateBuffer (&LocateHeapParams, StdHeader);
+ if (AgesaStatus != AGESA_SUCCESS) {
+ ASSERT (FALSE);
+ } else {
+ MemAffinityInfoHeaderPtr = (CRAT_MEMORY_AFFINITY_INFO_HEADER *) (LocateHeapParams.BufferPtr);
+ MemAffinityInfoHeaderPtr ++;
+ MemAffinityInfoEntryPtr = (CRAT_MEMORY_AFFINITY_INFO_ENTRY *) MemAffinityInfoHeaderPtr;
+ MemAffinityInfoHeaderPtr --;
+
+ // Get the number of CRAT memory affinity entries
+ NumOfMemAffinityInfoEntries = MemAffinityInfoHeaderPtr->NumOfMemAffinityInfoEntries;
+ Width = MemAffinityInfoHeaderPtr->MemoryWidth;
+
+ // Create CRAT memory affinity entries
+ IDS_HDT_CONSOLE (MAIN_FLOW, " CRAT memory affinity entries\n");
+ while (EntryNum < NumOfMemAffinityInfoEntries) {
+ // Add one CRAT memory entry
+ EntryPtr = (CRAT_MEMORY *) AddOneCratEntry (CRAT_TYPE_MEMORY, CratHeaderStructPtr, TableEnd, StdHeader);
+ EntryPtr->Flags.Enabled = 1;
+ EntryPtr->ProximityDomain = MemAffinityInfoEntryPtr->Domain;
+ EntryPtr->BaseAddressLow = MemAffinityInfoEntryPtr->BaseAddressLow;
+ EntryPtr->BaseAddressHigh = MemAffinityInfoEntryPtr->BaseAddressHigh;
+ EntryPtr->LengthLow = MemAffinityInfoEntryPtr->LengthLow;
+ EntryPtr->LengthHigh = MemAffinityInfoEntryPtr->LengthHigh;
+ EntryPtr->Width = Width;
+ IDS_HDT_CONSOLE (MAIN_FLOW, " Entry #%d\n", EntryNum);
+ IDS_HDT_CONSOLE (MAIN_FLOW, " Type: 0x%08x\n", EntryPtr->Type);
+ IDS_HDT_CONSOLE (MAIN_FLOW, " Length: 0x%08x\n", EntryPtr->Length);
+ IDS_HDT_CONSOLE (MAIN_FLOW, " Flags: %s %s %s\n", (EntryPtr->Flags.Enabled == 1) ? "Enabled" : "",
+ (EntryPtr->Flags.HotPluggable == 1) ? "EnHotPluggableabled" : "",
+ (EntryPtr->Flags.NonVolatile == 1) ? "NonVolatile" : ""
+ );
+ IDS_HDT_CONSOLE (MAIN_FLOW, " Proximity Domain: 0x%08x\n", EntryPtr->ProximityDomain);
+ IDS_HDT_CONSOLE (MAIN_FLOW, " Base Address Low: 0x%08x\n", EntryPtr->BaseAddressLow);
+ IDS_HDT_CONSOLE (MAIN_FLOW, " Base Address High: 0x%08x\n", EntryPtr->BaseAddressHigh);
+ IDS_HDT_CONSOLE (MAIN_FLOW, " Length Low: 0x%08x\n", EntryPtr->LengthLow);
+ IDS_HDT_CONSOLE (MAIN_FLOW, " Length High: 0x%08x\n", EntryPtr->LengthHigh);
+ IDS_HDT_CONSOLE (MAIN_FLOW, " Width: 0x%08x\n", EntryPtr->Width);
+ MemAffinityInfoEntryPtr ++;
+ EntryNum ++;
+ }
+ HeapDeallocateBuffer ((UINT32) AMD_MEM_CRAT_INFO_BUFFER_HANDLE, StdHeader);
+ }
+
+ return;
+}
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * This function will add cache entry.
+ *
+ * @param[in] CratHeaderStructPtr CRAT header pointer
+ * @param[in, out] TableEnd The end of CRAT
+ * @param[in, out] StdHeader Standard Head Pointer
+ *
+ */
+VOID
+MakeCacheEntry (
+ IN CRAT_HEADER *CratHeaderStructPtr,
+ IN OUT UINT8 **TableEnd,
+ IN OUT AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ CRAT_FAMILY_SERVICES *CratFamilyServices;
+
+ GetFeatureServicesOfSocket (&CratFamilyServiceTable, 0, (CONST VOID **)&CratFamilyServices, StdHeader);
+ CratFamilyServices->generateCratCacheEntry (CratHeaderStructPtr, TableEnd, StdHeader);
+ return;
+}
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * This function will add TLB entry.
+ *
+ * @param[in] CratHeaderStructPtr CRAT header pointer
+ * @param[in, out] TableEnd The end of CRAT
+ * @param[in, out] StdHeader Standard Head Pointer
+ *
+ */
+VOID
+MakeTLBEntry (
+ IN CRAT_HEADER *CratHeaderStructPtr,
+ IN OUT UINT8 **TableEnd,
+ IN OUT AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ CRAT_FAMILY_SERVICES *CratFamilyServices;
+
+ GetFeatureServicesOfSocket (&CratFamilyServiceTable, 0, (CONST VOID **)&CratFamilyServices, StdHeader);
+ CratFamilyServices->generateCratTLBEntry (CratHeaderStructPtr, TableEnd, StdHeader);
+ return;
+}
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * This function will add CRAT entry.
+ *
+ * @param[in] CratEntryType CRAT entry type
+ * @param[in] CratHeaderStructPtr CRAT header pointer
+ * @param[in, out] TableEnd The end of CRAT
+ * @param[in, out] StdHeader Standard Head Pointer
+ *
+ */
+UINT8 *
+AddOneCratEntry (
+ IN CRAT_ENTRY_TYPE CratEntryType,
+ IN CRAT_HEADER *CratHeaderStructPtr,
+ IN OUT UINT8 **TableEnd,
+ IN OUT AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ UINT8 *CurrentEntry;
+
+ CurrentEntry = *TableEnd;
+ CratHeaderStructPtr->TotalEntries++;
+ switch (CratEntryType) {
+ case CRAT_TYPE_HSA_PROC_UNIT:
+ *TableEnd += sizeof (CRAT_HSA_PROCESSING_UNIT);
+ ASSERT ((*TableEnd - (UINT8 *) CratHeaderStructPtr) <= CRAT_MAX_LENGTH);
+ CratHeaderStructPtr->Length += sizeof (CRAT_HSA_PROCESSING_UNIT);
+ ((CRAT_HSA_PROCESSING_UNIT *) CurrentEntry)->Type = (UINT8) CratEntryType;
+ ((CRAT_HSA_PROCESSING_UNIT *) CurrentEntry)->Length = sizeof (CRAT_HSA_PROCESSING_UNIT);
+ break;
+ case CRAT_TYPE_MEMORY:
+ *TableEnd += sizeof (CRAT_MEMORY);
+ ASSERT ((*TableEnd - (UINT8 *) CratHeaderStructPtr) <= CRAT_MAX_LENGTH);
+ CratHeaderStructPtr->Length += sizeof (CRAT_MEMORY);
+ ((CRAT_MEMORY *) CurrentEntry)->Type = (UINT8) CratEntryType;
+ ((CRAT_MEMORY *) CurrentEntry)->Length = sizeof (CRAT_MEMORY);
+ break;
+ case CRAT_TYPE_CACHE:
+ *TableEnd += sizeof (CRAT_CACHE);
+ ASSERT ((*TableEnd - (UINT8 *) CratHeaderStructPtr) <= CRAT_MAX_LENGTH);
+ CratHeaderStructPtr->Length += sizeof (CRAT_CACHE);
+ ((CRAT_CACHE *) CurrentEntry)->Type = (UINT8) CratEntryType;
+ ((CRAT_CACHE *) CurrentEntry)->Length = sizeof (CRAT_CACHE);
+ break;
+ case CRAT_TYPE_TLB:
+ *TableEnd += sizeof (CRAT_TLB);
+ ASSERT ((*TableEnd - (UINT8 *) CratHeaderStructPtr) <= CRAT_MAX_LENGTH);
+ CratHeaderStructPtr->Length += sizeof (CRAT_TLB);
+ ((CRAT_TLB *) CurrentEntry)->Type = (UINT8) CratEntryType;
+ ((CRAT_TLB *) CurrentEntry)->Length = sizeof (CRAT_TLB);
+ break;
+ case CRAT_TYPE_FPU:
+ *TableEnd += sizeof (CRAT_FPU);
+ ASSERT ((*TableEnd - (UINT8 *) CratHeaderStructPtr) <= CRAT_MAX_LENGTH);
+ CratHeaderStructPtr->Length += sizeof (CRAT_FPU);
+ ((CRAT_FPU *) CurrentEntry)->Type = (UINT8) CratEntryType;
+ ((CRAT_FPU *) CurrentEntry)->Length = sizeof (CRAT_FPU);
+ break;
+ case CRAT_TYPE_IO:
+ *TableEnd += sizeof (CRAT_IO);
+ ASSERT ((*TableEnd - (UINT8 *) CratHeaderStructPtr) <= CRAT_MAX_LENGTH);
+ CratHeaderStructPtr->Length += sizeof (CRAT_IO);
+ ((CRAT_IO *) CurrentEntry)->Type = (UINT8) CratEntryType;
+ ((CRAT_IO *) CurrentEntry)->Length = sizeof (CRAT_IO);
+ break;
+ default:
+ ASSERT (FALSE);
+ break;
+ }
+ return CurrentEntry;
+}
+
diff --git a/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuCrat.h b/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuCrat.h
new file mode 100644
index 0000000000..6b2b9d611a
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuCrat.h
@@ -0,0 +1,85 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * AMD AGESA CPU CRAT
+ *
+ * Contains code that declares the AGESA CRAT related APIs
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: CPU/Feature
+ * @e \$Revision: 84150 $ @e \$Date: 2012-12-12 15:46:25 -0600 (Wed, 12 Dec 2012) $
+ */
+/*
+ ******************************************************************************
+ *
+ * Copyright (c) 2008 - 2013, Advanced Micro Devices, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Advanced Micro Devices, Inc. nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ ******************************************************************************
+ */
+
+#ifndef _CPU_CRAT_H_
+#define _CPU_CRAT_H_
+
+/*----------------------------------------------------------------------------------------
+ * M I X E D (Definitions And Macros / Typedefs, Structures, Enums)
+ *----------------------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------------------
+ * D E F I N I T I O N S A N D M A C R O S
+ *----------------------------------------------------------------------------------------
+ */
+
+/**
+ * Make CRAT entry
+ *
+ * @param[in] CratHeaderStructPtr CRAT header pointer
+ * @param[in, out] TableEnd The end of CRAT
+ * @param[in, out] StdHeader Standard Head Pointer
+ *
+ */
+typedef VOID F_MAKE_CRAT_ENTRY (
+ IN CRAT_HEADER *CratHeaderStructPtr,
+ IN OUT UINT8 **TableEnd,
+ IN OUT AMD_CONFIG_PARAMS *StdHeader
+ );
+/// Reference to a Method.
+typedef F_MAKE_CRAT_ENTRY *PF_MAKE_CRAT_ENTRY;
+
+/**
+ * A struct that contains function pointe
+ */
+typedef struct _S_MAKE_CRAT_ENTRY {
+ PF_MAKE_CRAT_ENTRY MakeCratEntry; ///< Function Pointer, which points to the function which makes CRAT entry.
+} S_MAKE_CRAT_ENTRY;
+
+/*----------------------------------------------------------------------------------------
+ * T Y P E D E F S A N D S T R U C T U R E S
+ *----------------------------------------------------------------------------------------
+ */
+
+#endif // _CPU_CRAT_H_
diff --git a/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuDmi.c b/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuDmi.c
new file mode 100644
index 0000000000..6ff30d2faf
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuDmi.c
@@ -0,0 +1,872 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * AMD DMI Record Creation API, and related functions.
+ *
+ * Contains code that produce the DMI related information.
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: CPU
+ * @e \$Revision: 84150 $ @e \$Date: 2012-12-12 15:46:25 -0600 (Wed, 12 Dec 2012) $
+ *
+ */
+/*****************************************************************************
+ *
+ * Copyright (c) 2008 - 2013, Advanced Micro Devices, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Advanced Micro Devices, Inc. nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ ******************************************************************************
+ */
+
+/*----------------------------------------------------------------------------------------
+ * M O D U L E S U S E D
+ *----------------------------------------------------------------------------------------
+ */
+#include "AGESA.h"
+#include "amdlib.h"
+#include "OptionDmi.h"
+#include "cpuLateInit.h"
+#include "cpuServices.h"
+#include "cpuRegisters.h"
+#include "GeneralServices.h"
+#include "heapManager.h"
+#include "Ids.h"
+#include "cpuFamilyTranslation.h"
+#include "Filecode.h"
+CODE_GROUP (G3_DXE)
+RDATA_GROUP (G3_DXE)
+
+#define FILECODE PROC_CPU_FEATURE_CPUDMI_FILECODE
+/*----------------------------------------------------------------------------------------
+ * D E F I N I T I O N S A N D M A C R O S
+ *----------------------------------------------------------------------------------------
+ */
+extern OPTION_DMI_CONFIGURATION OptionDmiConfiguration; // global user config record
+
+/*----------------------------------------------------------------------------------------
+ * T Y P E D E F S A N D S T R U C T U R E S
+ *----------------------------------------------------------------------------------------
+ */
+CHAR8 ROMDATA str_ProcManufacturer[] = "Advanced Micro Devices, Inc.";
+/*----------------------------------------------------------------------------------------
+ * P R O T O T Y P E S O F L O C A L F U N C T I O N S
+ *----------------------------------------------------------------------------------------
+ */
+UINT16
+STATIC
+AdjustGranularity (
+ IN UINT32 *CacheSizePtr
+ );
+
+VOID
+STATIC
+IntToString (
+ IN OUT CHAR8 *String,
+ IN UINT8 *Integer,
+ IN UINT8 SizeInByte
+);
+
+AGESA_STATUS
+GetDmiInfoStub (
+ IN OUT AMD_CONFIG_PARAMS *StdHeader,
+ IN OUT DMI_INFO **DmiTable
+ );
+
+AGESA_STATUS
+GetDmiInfoMain (
+ IN OUT AMD_CONFIG_PARAMS *StdHeader,
+ IN OUT DMI_INFO **DmiTable
+ );
+
+AGESA_STATUS
+ReleaseDmiBufferStub (
+ IN OUT AMD_CONFIG_PARAMS *StdHeader
+ );
+
+AGESA_STATUS
+ReleaseDmiBuffer (
+ IN OUT AMD_CONFIG_PARAMS *StdHeader
+ );
+
+/*----------------------------------------------------------------------------------------
+ * E X P O R T E D F U N C T I O N S
+ *----------------------------------------------------------------------------------------
+ */
+
+/*---------------------------------------------------------------------------------------
+ * L O C A L F U N C T I O N S
+ *---------------------------------------------------------------------------------------
+ */
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * CreateDmiRecords
+ *
+ * Description:
+ * This function creates DMI/SMBios records pertinent to the processor
+ * SMBIOS type 4, type 7, and type 40.
+ *
+ * Parameters:
+ * @param[in, out] *StdHeader
+ * @param[in, out] **DmiTable
+ *
+ * @retval AGESA_STATUS
+ *
+ */
+
+AGESA_STATUS
+CreateDmiRecords (
+ IN OUT AMD_CONFIG_PARAMS *StdHeader,
+ IN OUT DMI_INFO **DmiTable
+ )
+{
+ AGESA_TESTPOINT (TpProcCpuEntryDmi, StdHeader);
+ return ((*(OptionDmiConfiguration.DmiFeature)) (StdHeader, DmiTable));
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ * GetDmiInfoStub
+ *
+ * Description:
+ * This is the default routine for use when the DMI option is NOT requested.
+ * The option install process will create and fill the transfer vector with
+ * the address of the proper routine (Main or Stub). The link optimizer will
+ * strip out of the .DLL the routine that is not used.
+ *
+ * Parameters:
+ * @param[in, out] *StdHeader
+ * @param[in, out] **DmiTable
+ *
+ * @retval AGESA_STATUS
+ *
+ */
+AGESA_STATUS
+GetDmiInfoStub (
+ IN OUT AMD_CONFIG_PARAMS *StdHeader,
+ IN OUT DMI_INFO **DmiTable
+ )
+{
+ return AGESA_UNSUPPORTED;
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ * GetDmiInfoMain
+ *
+ * Description:
+ * This is the common routine for getting Dmi type4 and type7 CPU related information.
+ *
+ * Parameters:
+ * @param[in, out] *StdHeader
+ * @param[in, out] **DmiTable
+ *
+ * @retval AGESA_STATUS
+ *
+ */
+AGESA_STATUS
+GetDmiInfoMain (
+ IN OUT AMD_CONFIG_PARAMS *StdHeader,
+ IN OUT DMI_INFO **DmiTable
+ )
+{
+ UINT8 Socket;
+ UINT8 Channel;
+ UINT8 Dimm;
+ UINT16 Index;
+ UINT16 DimmIndex;
+ UINT8 MaxPhysicalDimms;
+ UINT8 MaxLogicalDimms;
+ UINT32 MaxCapacity;
+ UINT64 MsrData;
+ UINT64 Value64;
+ UINT8 TypeDetail;
+ UINT32 *TotalMemSizePtr;
+ BOOLEAN FamilyNotFound;
+ AGESA_STATUS Flag;
+ AGESA_STATUS CalledStatus;
+ AP_EXE_PARAMS ApParams;
+ UINT8 *MemInfo;
+ DMI_T17_MEMORY_TYPE *DmiType17MemTypePtr;
+ DMI_T17_MEMORY_TYPE MemType;
+ MEM_DMI_PHYSICAL_DIMM_INFO *DmiPhysicalDimmInfoTable;
+ MEM_DMI_LOGICAL_DIMM_INFO *DmiLogicalDimmInfoTable;
+ DMI_INFO *DmiBufferPtr;
+ ALLOCATE_HEAP_PARAMS AllocateHeapParams;
+ LOCATE_HEAP_PTR LocateHeapParams;
+ CPU_LOGICAL_ID LogicalId;
+ PROC_FAMILY_TABLE *ProcData;
+ CPU_GET_MEM_INFO CpuGetMemInfo;
+
+ MsrData = 0;
+ Flag = TRUE;
+ ProcData = NULL;
+ MemInfo = NULL;
+ DmiBufferPtr = *DmiTable;
+ FamilyNotFound = TRUE;
+
+ GetLogicalIdOfCurrentCore (&LogicalId, StdHeader);
+ for (Index = 0; Index < OptionDmiConfiguration.NumEntries; Index++) {
+ ProcData = (PROC_FAMILY_TABLE *) ((*OptionDmiConfiguration.FamilyList)[Index]);
+ if ((ProcData->ProcessorFamily & LogicalId.Family) != 0) {
+ FamilyNotFound = FALSE;
+ break;
+ }
+ }
+
+ if (FamilyNotFound) {
+ return AGESA_ERROR;
+ }
+
+ if (DmiBufferPtr == NULL) {
+ //
+ // Allocate a buffer by heap function
+ //
+ AllocateHeapParams.BufferHandle = AMD_DMI_INFO_BUFFER_HANDLE;
+ AllocateHeapParams.RequestedBufferSize = sizeof (DMI_INFO);
+ AllocateHeapParams.Persist = HEAP_SYSTEM_MEM;
+
+ if (HeapAllocateBuffer (&AllocateHeapParams, StdHeader) != AGESA_SUCCESS) {
+ return AGESA_ERROR;
+ }
+
+ DmiBufferPtr = (DMI_INFO *) AllocateHeapParams.BufferPtr;
+ *DmiTable = DmiBufferPtr;
+ }
+
+ IDS_HDT_CONSOLE (CPU_TRACE, " DMI is enabled\n");
+
+ // Fill with 0x00
+ LibAmdMemFill (DmiBufferPtr, 0x00, sizeof (DMI_INFO), StdHeader);
+
+ //
+ // Get CPU information
+ //
+
+ // Run GetType4Type7Info on all core0s.
+ ApParams.StdHeader = *StdHeader;
+ ApParams.FunctionNumber = AP_LATE_TASK_GET_TYPE4_TYPE7;
+ ApParams.RelatedDataBlock = (VOID *) DmiBufferPtr;
+ ApParams.RelatedBlockLength = sizeof (DMI_INFO);
+ CalledStatus = RunLateApTaskOnAllCore0s (&ApParams, StdHeader);
+ if (CalledStatus > Flag) {
+ Flag = CalledStatus;
+ }
+ CalledStatus = GetType4Type7Info (&ApParams);
+ if (CalledStatus > Flag) {
+ Flag = CalledStatus;
+ }
+
+ //------------------------------
+ // T Y P E 16 17 19 20
+ //------------------------------
+
+ LocateHeapParams.BufferHandle = AMD_DMI_MEM_DEV_INFO_HANDLE;
+ if (HeapLocateBuffer (&LocateHeapParams, StdHeader) != AGESA_SUCCESS) {
+ if (Flag < AGESA_ERROR) {
+ Flag = AGESA_ERROR;
+ }
+ } else {
+ MemInfo = (UINT8 *) (LocateHeapParams.BufferPtr);
+ // Max number of physical DIMMs
+ MaxPhysicalDimms = *MemInfo;
+ MemInfo ++;
+ // Type Detail;
+ TypeDetail = *MemInfo;
+ MemInfo ++;
+ // Pointer to total memory size
+ TotalMemSizePtr = (UINT32 *) MemInfo;
+ MemInfo += sizeof (UINT32);
+ // Memory Type
+ DmiType17MemTypePtr = (DMI_T17_MEMORY_TYPE *) MemInfo;
+ MemType = *DmiType17MemTypePtr;
+ DmiType17MemTypePtr ++;
+ MemInfo = (UINT8 *) DmiType17MemTypePtr;
+ // Pointer to DMI info of Physical DIMMs
+ DmiPhysicalDimmInfoTable = (MEM_DMI_PHYSICAL_DIMM_INFO *) MemInfo;
+ // TYPE 16
+ DmiBufferPtr->T16.Location = 0x03;
+ DmiBufferPtr->T16.Use = 0x03;
+
+ // Gather memory information
+ ProcData->DmiGetMemInfo (&CpuGetMemInfo, StdHeader);
+
+ if (CpuGetMemInfo.EccCapable) {
+ DmiBufferPtr->T16.MemoryErrorCorrection = Dmi16MultiBitEcc;
+ } else {
+ DmiBufferPtr->T16.MemoryErrorCorrection = Dmi16NoneErrCorrection;
+ }
+
+ MaxCapacity = *TotalMemSizePtr;
+ // For the total size >= 2TB case, we need leave MaximumCapacity (offset 07h) to 80000000h
+ // and fill the size in bytes into ExtMaxCapacity (offset 0Fh).
+ if (MaxCapacity < 0x200000) {
+ DmiBufferPtr->T16.MaximumCapacity = MaxCapacity << 10;
+ DmiBufferPtr->T16.ExtMaxCapacity = 0;
+ } else {
+ DmiBufferPtr->T16.MaximumCapacity = 0x80000000;
+ DmiBufferPtr->T16.ExtMaxCapacity = (UINT64) MaxCapacity << 20;
+ }
+
+ DmiBufferPtr->T16.NumberOfMemoryDevices = (UINT16) MaxPhysicalDimms;
+
+ // TYPE 17 entries are organized by physical DIMMs
+ for (DimmIndex = 0; DimmIndex < MaxPhysicalDimms; DimmIndex ++, DmiPhysicalDimmInfoTable ++) {
+ Socket = DmiPhysicalDimmInfoTable->Socket;
+ Channel = DmiPhysicalDimmInfoTable->Channel;
+ Dimm = DmiPhysicalDimmInfoTable->Dimm;
+
+ DmiBufferPtr->T17[Socket][Channel][Dimm].Handle = DmiPhysicalDimmInfoTable->Handle;
+ DmiBufferPtr->T17[Socket][Channel][Dimm].TotalWidth = DmiPhysicalDimmInfoTable->TotalWidth;
+ DmiBufferPtr->T17[Socket][Channel][Dimm].DataWidth = DmiPhysicalDimmInfoTable->DataWidth;
+ DmiBufferPtr->T17[Socket][Channel][Dimm].MemorySize = DmiPhysicalDimmInfoTable->MemorySize;
+ DmiBufferPtr->T17[Socket][Channel][Dimm].FormFactor = DmiPhysicalDimmInfoTable->FormFactor;
+ DmiBufferPtr->T17[Socket][Channel][Dimm].DeviceSet = 0;
+
+ DmiBufferPtr->T17[Socket][Channel][Dimm].DeviceLocator[0] = 'D';
+ DmiBufferPtr->T17[Socket][Channel][Dimm].DeviceLocator[1] = 'I';
+ DmiBufferPtr->T17[Socket][Channel][Dimm].DeviceLocator[2] = 'M';
+ DmiBufferPtr->T17[Socket][Channel][Dimm].DeviceLocator[3] = 'M';
+ DmiBufferPtr->T17[Socket][Channel][Dimm].DeviceLocator[4] = ' ';
+ DmiBufferPtr->T17[Socket][Channel][Dimm].DeviceLocator[5] = Dimm + 0x30;
+ DmiBufferPtr->T17[Socket][Channel][Dimm].DeviceLocator[6] = '\0';
+ DmiBufferPtr->T17[Socket][Channel][Dimm].DeviceLocator[7] = '\0';
+
+ DmiBufferPtr->T17[Socket][Channel][Dimm].BankLocator[0] = 'C';
+ DmiBufferPtr->T17[Socket][Channel][Dimm].BankLocator[1] = 'H';
+ DmiBufferPtr->T17[Socket][Channel][Dimm].BankLocator[2] = 'A';
+ DmiBufferPtr->T17[Socket][Channel][Dimm].BankLocator[3] = 'N';
+ DmiBufferPtr->T17[Socket][Channel][Dimm].BankLocator[4] = 'N';
+ DmiBufferPtr->T17[Socket][Channel][Dimm].BankLocator[5] = 'E';
+ DmiBufferPtr->T17[Socket][Channel][Dimm].BankLocator[6] = 'L';
+ DmiBufferPtr->T17[Socket][Channel][Dimm].BankLocator[7] = ' ';
+ DmiBufferPtr->T17[Socket][Channel][Dimm].BankLocator[8] = Channel + 0x41;
+ DmiBufferPtr->T17[Socket][Channel][Dimm].BankLocator[9] = '\0';
+
+ DmiBufferPtr->T17[Socket][Channel][Dimm].MemoryType = MemType;
+ if (DmiPhysicalDimmInfoTable->MemorySize != 0) {
+ DmiBufferPtr->T17[Socket][Channel][Dimm].TypeDetail.Synchronous = 1;
+ if (TypeDetail == 1) {
+ DmiBufferPtr->T17[Socket][Channel][Dimm].TypeDetail.Registered = 1;
+ } else if (TypeDetail == 2) {
+ DmiBufferPtr->T17[Socket][Channel][Dimm].TypeDetail.Unbuffered = 1;
+ } else {
+ DmiBufferPtr->T17[Socket][Channel][Dimm].TypeDetail.Unknown = 1;
+ }
+ }
+ DmiBufferPtr->T17[Socket][Channel][Dimm].Speed = DmiPhysicalDimmInfoTable->Speed;
+
+ DmiBufferPtr->T17[Socket][Channel][Dimm].ManufacturerIdCode = DmiPhysicalDimmInfoTable->ManufacturerIdCode;
+
+ IntToString (DmiBufferPtr->T17[Socket][Channel][Dimm].SerialNumber, DmiPhysicalDimmInfoTable->SerialNumber, (sizeof DmiBufferPtr->T17[Socket][Channel][Dimm].SerialNumber - 1) / 2);
+
+ LibAmdMemCopy (&DmiBufferPtr->T17[Socket][Channel][Dimm].PartNumber, &DmiPhysicalDimmInfoTable->PartNumber, sizeof (DmiBufferPtr->T17[Socket][Channel][Dimm].PartNumber), StdHeader);
+ DmiBufferPtr->T17[Socket][Channel][Dimm].PartNumber[18] = 0;
+
+ DmiBufferPtr->T17[Socket][Channel][Dimm].Attributes = DmiPhysicalDimmInfoTable->Attributes;
+ DmiBufferPtr->T17[Socket][Channel][Dimm].ExtSize = DmiPhysicalDimmInfoTable->ExtSize;
+ DmiBufferPtr->T17[Socket][Channel][Dimm].ConfigSpeed = DmiPhysicalDimmInfoTable->ConfigSpeed;
+ }
+
+ // Max number of logical DIMMs
+ MemInfo = (UINT8 *) DmiPhysicalDimmInfoTable;
+ MaxLogicalDimms = *MemInfo;
+ MemInfo ++;
+
+ // Pointer to DMI info of Logical DIMMs
+ DmiLogicalDimmInfoTable = (MEM_DMI_LOGICAL_DIMM_INFO *) MemInfo;
+
+ // TYPE 20 entries are organized by logical DIMMs
+ for (DimmIndex = 0; DimmIndex < MaxLogicalDimms; DimmIndex ++, DmiLogicalDimmInfoTable ++) {
+ Socket = DmiLogicalDimmInfoTable->Socket;
+ Channel = DmiLogicalDimmInfoTable->Channel;
+ Dimm = DmiLogicalDimmInfoTable->Dimm;
+ DmiBufferPtr->T20[Socket][Channel][Dimm].PartitionRowPosition = 0xFF;
+ DmiBufferPtr->T20[Socket][Channel][Dimm].InterleavePosition = 0xFF;
+ DmiBufferPtr->T20[Socket][Channel][Dimm].InterleavedDataDepth = 0xFF;
+
+ if (DmiLogicalDimmInfoTable->DimmPresent) {
+ DmiBufferPtr->T20[Socket][Channel][Dimm].MemoryDeviceHandle = DmiLogicalDimmInfoTable->MemoryDeviceHandle;
+ DmiBufferPtr->T20[Socket][Channel][Dimm].StartingAddr = DmiLogicalDimmInfoTable->StartingAddr;
+ DmiBufferPtr->T20[Socket][Channel][Dimm].EndingAddr = DmiLogicalDimmInfoTable->EndingAddr;
+ DmiBufferPtr->T20[Socket][Channel][Dimm].ExtStartingAddr = DmiLogicalDimmInfoTable->ExtStartingAddr;
+ DmiBufferPtr->T20[Socket][Channel][Dimm].ExtEndingAddr = DmiLogicalDimmInfoTable->ExtEndingAddr;
+ }
+ }
+
+ // TYPE 19
+ DmiBufferPtr->T19.StartingAddr = 0;
+ DmiBufferPtr->T19.ExtStartingAddr = 0;
+ DmiBufferPtr->T19.ExtEndingAddr = 0;
+
+ // If Ending Address >= 0xFFFFFFFF, update Starting Address (offset 04h) & Ending Address (offset 08h) to 0xFFFFFFFF,
+ // and use the Extended Starting Address (offset 0Fh) & Extended Ending Address (offset 17h) instead.
+ Value64 = (UINT64) ((MaxCapacity << 10) - 1);
+ // Value64 = EndingAddr = MaxCapacity in KByte - 1
+ if (Value64 >= ((UINT64) 0xFFFFFFFF)) {
+ DmiBufferPtr->T19.StartingAddr = 0xFFFFFFFFUL;
+ DmiBufferPtr->T19.EndingAddr = 0xFFFFFFFFUL;
+ // In Byte
+ DmiBufferPtr->T19.ExtEndingAddr = Value64 << 10;
+ } else {
+ // In KByte
+ DmiBufferPtr->T19.EndingAddr = (UINT32) Value64;
+ }
+
+ DmiBufferPtr->T19.PartitionWidth = 0xFF;
+ }
+ return (Flag);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * GetType4Type7Info
+ *
+ * Description:
+ * This routine should be run on core 0 of every socket. It creates DMI type 4 and type 7 tables.
+ *
+ * Parameters:
+ * @param[in] ApExeParams Handle to config for library and services.
+ *
+ * @retval AGESA_STATUS
+ *
+ * Processing:
+ *
+ */
+AGESA_STATUS
+GetType4Type7Info (
+ IN AP_EXE_PARAMS *ApExeParams
+ )
+{
+ UINT8 ByteIndexInUint64;
+ UINT16 Index;
+ UINT32 SocketNum;
+ UINT32 IgnoredModule;
+ UINT32 IgnoredCore;
+ UINT64 MsrData;
+ DMI_INFO *DmiBufferPtr;
+ AGESA_STATUS IgnoredSts;
+ AGESA_STATUS Flag;
+ BOOLEAN FamilyNotFound;
+ CPUID_DATA CpuId;
+ CPU_TYPE_INFO CpuInfo;
+ PROC_FAMILY_TABLE *ProcData;
+ CPU_LOGICAL_ID LogicalID;
+
+ Flag = TRUE;
+ DmiBufferPtr = (DMI_INFO *) ApExeParams->RelatedDataBlock;
+ GetLogicalIdOfCurrentCore (&LogicalID, &ApExeParams->StdHeader);
+
+ ProcData = NULL;
+ FamilyNotFound = TRUE;
+ for (Index = 0; Index < OptionDmiConfiguration.NumEntries; Index++) {
+ ProcData = (PROC_FAMILY_TABLE *) ((*OptionDmiConfiguration.FamilyList)[Index]);
+ if ((ProcData->ProcessorFamily & LogicalID.Family) != 0) {
+ FamilyNotFound = FALSE;
+ break;
+ }
+ }
+
+ if (FamilyNotFound) {
+ return AGESA_ERROR;
+ }
+
+ ProcData->DmiGetCpuInfo (&CpuInfo, &ApExeParams->StdHeader);
+
+ // ------------------------------
+ // T Y P E 4
+ // ------------------------------
+
+ IdentifyCore (&ApExeParams->StdHeader, &SocketNum, &IgnoredModule, &IgnoredCore, &IgnoredSts);
+
+ // Type 4 Offset 0x05, Processor Type
+ DmiBufferPtr->T4[SocketNum].T4ProcType = CENTRAL_PROCESSOR;
+
+ // Type 4 Offset 0x06, Processor Family
+ ProcData->DmiGetT4ProcFamily (&DmiBufferPtr->T4[SocketNum].T4ProcFamily, ProcData, &CpuInfo, &ApExeParams->StdHeader);
+
+ if (DmiBufferPtr->T4[SocketNum].T4ProcFamily == P_UPGRADE_UNKNOWN) {
+ Flag = AGESA_ERROR;
+ }
+
+ // Type4 Offset 0x08, Processor ID
+ LibAmdCpuidRead (AMD_CPUID_APICID_LPC_BID, &CpuId, &ApExeParams->StdHeader);
+ DmiBufferPtr->T4[SocketNum].T4ProcId.ProcIdLsd = CpuId.EAX_Reg;
+ DmiBufferPtr->T4[SocketNum].T4ProcId.ProcIdMsd = CpuId.EDX_Reg;
+
+ // Type4 Offset 0x11, Voltage
+ DmiBufferPtr->T4[SocketNum].T4Voltage = ProcData->DmiGetVoltage (&ApExeParams->StdHeader);
+
+ // Type4 Offset 0x12, External Clock
+ DmiBufferPtr->T4[SocketNum].T4ExternalClock = ProcData->DmiGetExtClock (&ApExeParams->StdHeader);
+
+ // Type4 Offset 0x14, Max Speed
+ DmiBufferPtr->T4[SocketNum].T4MaxSpeed = ProcData->DmiGetMaxSpeed (&ApExeParams->StdHeader);
+
+ // Type4 Offset 0x16, Current Speed
+ DmiBufferPtr->T4[SocketNum].T4CurrentSpeed = DmiBufferPtr->T4[SocketNum].T4MaxSpeed;
+
+ // Type4 Offset 0x18, Status
+ DmiBufferPtr->T4[SocketNum].T4Status = SOCKET_POPULATED | CPU_STATUS_ENABLED;
+
+ // Type4 Offset 0x19, Processor Upgrade
+ DmiBufferPtr->T4[SocketNum].T4ProcUpgrade = CpuInfo.ProcUpgrade;
+
+ // Type4 Offset 0x23, 0x24 and 0x25, Core Count, Core Enabled and Thread Count
+ DmiBufferPtr->T4[SocketNum].T4CoreCount = CpuInfo.TotalCoreNumber + 1;
+ DmiBufferPtr->T4[SocketNum].T4CoreEnabled = CpuInfo.EnabledCoreNumber + 1;
+ DmiBufferPtr->T4[SocketNum].T4ThreadCount = CpuInfo.EnabledCoreNumber + 1;
+
+ // Type4 Offset 0x26, Processor Characteristics
+ DmiBufferPtr->T4[SocketNum].T4ProcCharacteristics = P_CHARACTERISTICS;
+
+ // Type4 Offset 0x28, Processor Family 2
+ DmiBufferPtr->T4[SocketNum].T4ProcFamily2 = DmiBufferPtr->T4[SocketNum].T4ProcFamily;
+
+ // Type4 ProcVersion
+ for (Index = 0; Index <= 5; Index++) {
+ LibAmdMsrRead ((MSR_CPUID_NAME_STRING0 + Index), &MsrData, &ApExeParams->StdHeader);
+ for (ByteIndexInUint64 = 0; ByteIndexInUint64 <= 7; ByteIndexInUint64++) {
+ DmiBufferPtr->T4[SocketNum].T4ProcVersion[Index * 8 + ByteIndexInUint64] = (UINT8) (MsrData >> (8 * ByteIndexInUint64));
+ }
+ }
+
+ // Type4 Manufacturer
+ ASSERT (PROC_MANU_LENGTH >= sizeof (str_ProcManufacturer));
+ LibAmdMemCopy (DmiBufferPtr->T4[SocketNum].T4ProcManufacturer, str_ProcManufacturer, sizeof (str_ProcManufacturer), &ApExeParams->StdHeader);
+
+ //------------------------------
+ // T Y P E 7
+ //------------------------------
+
+ // Type7 Offset 0x05, Cache Configuration
+ DmiBufferPtr->T7L1[SocketNum].T7CacheCfg = CACHE_CFG_L1;
+ DmiBufferPtr->T7L2[SocketNum].T7CacheCfg = CACHE_CFG_L2;
+ DmiBufferPtr->T7L3[SocketNum].T7CacheCfg = CACHE_CFG_L3;
+
+ // Type7 Offset 0x07 and 09, Maximum Cache Size and Installed Size
+
+ // Maximum L1 cache size
+ DmiBufferPtr->T7L1[SocketNum].T7MaxCacheSize = AdjustGranularity (&CpuInfo.CacheInfo.L1CacheSize);
+
+ // Installed L1 cache size
+ DmiBufferPtr->T7L1[SocketNum].T7InstallSize = DmiBufferPtr->T7L1[SocketNum].T7MaxCacheSize;
+
+ // Maximum L2 cache size
+ DmiBufferPtr->T7L2[SocketNum].T7MaxCacheSize = AdjustGranularity (&CpuInfo.CacheInfo.L2CacheSize);
+
+ // Installed L2 cache size
+ DmiBufferPtr->T7L2[SocketNum].T7InstallSize = DmiBufferPtr->T7L2[SocketNum].T7MaxCacheSize;
+
+ // Maximum L3 cache size
+ DmiBufferPtr->T7L3[SocketNum].T7MaxCacheSize = AdjustGranularity (&CpuInfo.CacheInfo.L3CacheSize);
+
+ // Installed L3 cache size
+ DmiBufferPtr->T7L3[SocketNum].T7InstallSize = DmiBufferPtr->T7L3[SocketNum].T7MaxCacheSize;
+
+ // Type7 Offset 0x0B and 0D, Supported SRAM Type and Current SRAM Type
+ DmiBufferPtr->T7L1[SocketNum].T7SupportedSramType = SRAM_TYPE;
+ DmiBufferPtr->T7L1[SocketNum].T7CurrentSramType = SRAM_TYPE;
+ DmiBufferPtr->T7L2[SocketNum].T7SupportedSramType = SRAM_TYPE;
+ DmiBufferPtr->T7L2[SocketNum].T7CurrentSramType = SRAM_TYPE;
+ DmiBufferPtr->T7L3[SocketNum].T7SupportedSramType = SRAM_TYPE;
+ DmiBufferPtr->T7L3[SocketNum].T7CurrentSramType = SRAM_TYPE;
+
+ // Type7 Offset 0x0F, Cache Speed
+ DmiBufferPtr->T7L1[SocketNum].T7CacheSpeed = 1;
+ DmiBufferPtr->T7L2[SocketNum].T7CacheSpeed = 1;
+ DmiBufferPtr->T7L3[SocketNum].T7CacheSpeed = 1;
+
+ // Type7 Offset 0x10, Error Correction Type
+ DmiBufferPtr->T7L1[SocketNum].T7ErrorCorrectionType = ERR_CORRECT_TYPE;
+ DmiBufferPtr->T7L2[SocketNum].T7ErrorCorrectionType = ERR_CORRECT_TYPE;
+ DmiBufferPtr->T7L3[SocketNum].T7ErrorCorrectionType = ERR_CORRECT_TYPE;
+
+ // Type7 Offset 0x11, System Cache Type
+ DmiBufferPtr->T7L1[SocketNum].T7SystemCacheType = CACHE_TYPE;
+ DmiBufferPtr->T7L2[SocketNum].T7SystemCacheType = CACHE_TYPE;
+ DmiBufferPtr->T7L3[SocketNum].T7SystemCacheType = CACHE_TYPE;
+
+ // Type7 Offset 0x12, Associativity
+ DmiBufferPtr->T7L1[SocketNum].T7Associativity = CpuInfo.CacheInfo.L1CacheAssoc;
+ DmiBufferPtr->T7L2[SocketNum].T7Associativity = CpuInfo.CacheInfo.L2CacheAssoc;
+ DmiBufferPtr->T7L3[SocketNum].T7Associativity = CpuInfo.CacheInfo.L3CacheAssoc;
+
+ return (Flag);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ * DmiGetT4ProcFamilyFromBrandId
+ *
+ * Description:
+ * This is the common routine for getting Type 4 processor family information from brand ID
+ *
+ * Parameters:
+ * @param[in, out] *T4ProcFamily Pointer to type 4 processor family information
+ * @param[in] *CpuDmiProcFamilyTable Pointer to DMI family special service
+ * @param[in] *CpuInfo Pointer to CPU_TYPE_INFO struct
+ * @param[in, out] *StdHeader Standard Head Pointer
+ *
+ * @retval AGESA_STATUS
+ *
+ */
+VOID
+DmiGetT4ProcFamilyFromBrandId (
+ IN OUT UINT8 *T4ProcFamily,
+ IN PROC_FAMILY_TABLE *CpuDmiProcFamilyTable,
+ IN CPU_TYPE_INFO *CpuInfo,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ UINT16 Index;
+ *T4ProcFamily = P_UPGRADE_UNKNOWN;
+ if (CpuInfo->BrandId.Model != P_ENGINEERING_SAMPLE) {
+ for (Index = 0; Index < CpuDmiProcFamilyTable->LenBrandList; Index++) {
+ if ((CpuDmiProcFamilyTable->DmiBrandList[Index].PackageType == 'x' || CpuDmiProcFamilyTable->DmiBrandList[Index].PackageType == CpuInfo->PackageType) &&
+ (CpuDmiProcFamilyTable->DmiBrandList[Index].PgOfBrandId == 'x' || CpuDmiProcFamilyTable->DmiBrandList[Index].PgOfBrandId == CpuInfo->BrandId.Pg) &&
+ (CpuDmiProcFamilyTable->DmiBrandList[Index].NumberOfCores == 'x' || CpuDmiProcFamilyTable->DmiBrandList[Index].NumberOfCores == CpuInfo->TotalCoreNumber) &&
+ (CpuDmiProcFamilyTable->DmiBrandList[Index].String1ofBrandId == 'x' || CpuDmiProcFamilyTable->DmiBrandList[Index].String1ofBrandId == CpuInfo->BrandId.String1)) {
+ *T4ProcFamily = CpuDmiProcFamilyTable->DmiBrandList[Index].ValueSetToDmiTable;
+ break;
+ }
+ }
+ }
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * GetNameString
+ *
+ * Description:
+ * Get name string from MSR_C001_00[35:30]
+ *
+ * Parameters:
+ * @param[in, out] *String Pointer to name string
+ * @param[in, out] *StdHeader
+ *
+ */
+VOID
+GetNameString (
+ IN OUT CHAR8 *String,
+ IN OUT AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ UINT8 i;
+ UINT8 StringIndex;
+ UINT8 MsrIndex;
+ UINT64 MsrData;
+
+ StringIndex = 0;
+ for (MsrIndex = 0; MsrIndex <= 5; MsrIndex++) {
+ LibAmdMsrRead ((MSR_CPUID_NAME_STRING0 + MsrIndex), &MsrData, StdHeader);
+ for (i = 0; i < 8; i++) {
+ String[StringIndex] = (CHAR8) (MsrData >> (8 * i));
+ StringIndex++;
+ }
+ }
+ String[StringIndex] = '\0';
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * IsSourceStrContainTargetStr
+ *
+ * Description:
+ * check if source string contains target string.
+ *
+ * Parameters:
+ * @param[in, out] *SourceStr Pointer to source CHAR array
+ * @param[in, out] *TargetStr Pointer to target CHAR array
+ * @param[in, out] *StdHeader
+ *
+ * @retval TRUE Target string is contained in the source string
+ * @retval FALSE Target string is not contained in the source string
+ */
+BOOLEAN
+IsSourceStrContainTargetStr (
+ IN OUT CHAR8 *SourceStr,
+ IN OUT CONST CHAR8 *TargetStr,
+ IN OUT AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ BOOLEAN IsContained;
+ UINT32 SourceStrIndex;
+ UINT32 TargetStrIndex;
+ CHAR8 TargetChar;
+
+ IsContained = FALSE;
+ if ((TargetStr != NULL) && (SourceStr != NULL)) {
+ for (SourceStrIndex = 0; SourceStr[SourceStrIndex] != '\0'; SourceStrIndex++) {
+ // Compare TrgString with SrcString from frist charactor to the '\0'
+ for (TargetStrIndex = 0; TargetStr[TargetStrIndex] != '\0'; TargetStrIndex++) {
+ if (TargetStr[TargetStrIndex] != SourceStr[SourceStrIndex + TargetStrIndex]) {
+ // if it's not match, try to check the upcase/lowcase
+ TargetChar = 0;
+ if (TargetStr[TargetStrIndex] >= 'a' && TargetStr[TargetStrIndex] <= 'z') {
+ TargetChar = TargetStr[TargetStrIndex] - ('a' - 'A');
+ } else if (TargetStr[TargetStrIndex] >= 'A' && TargetStr[TargetStrIndex] <= 'Z') {
+ TargetChar = TargetStr[TargetStrIndex] + ('a' - 'A');
+ }
+ // compare again
+ if (TargetChar != SourceStr[SourceStrIndex + TargetStrIndex]) {
+ break;
+ }
+ }
+ }
+
+ if ((TargetStr[TargetStrIndex] == '\0') && (TargetStrIndex != 0)) {
+ IsContained = TRUE;
+ break;
+ }
+ }
+ }
+ return IsContained;
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * AdjustGranularity
+ *
+ * Description:
+ * If cache size is greater than or equal to 32M, then set granularity
+ * to 64K. otherwise, set granularity to 1K
+ *
+ * Parameters:
+ * @param[in] *CacheSizePtr
+ *
+ * @retval CacheSize
+ *
+ * Processing:
+ *
+ */
+UINT16
+STATIC
+AdjustGranularity (
+ IN UINT32 *CacheSizePtr
+ )
+{
+ UINT16 CacheSize;
+
+ if (*CacheSizePtr >= 0x8000) {
+ CacheSize = (UINT16) (*CacheSizePtr / 64);
+ CacheSize |= 0x8000;
+ } else {
+ CacheSize = (UINT16) *CacheSizePtr;
+ }
+
+ return (CacheSize);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ * ReleaseDmiBufferStub
+ *
+ * Description:
+ * This is the default routine for use when the DMI option is NOT requested.
+ *
+ * Parameters:
+ * @param[in, out] *StdHeader
+ *
+ * @retval AGESA_STATUS
+ *
+ */
+AGESA_STATUS
+ReleaseDmiBufferStub (
+ IN OUT AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ return AGESA_UNSUPPORTED;
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ * ReleaseDmiBuffer
+ *
+ * Description:
+ * Deallocate DMI buffer
+ *
+ * Parameters:
+ * @param[in, out] *StdHeader
+ *
+ * @retval AGESA_STATUS
+ *
+ */
+AGESA_STATUS
+ReleaseDmiBuffer (
+ IN OUT AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ HeapDeallocateBuffer ((UINT32) AMD_DMI_MEM_DEV_INFO_HANDLE, StdHeader);
+
+ return AGESA_SUCCESS;
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * IntToString
+ *
+ * Description:
+ * Translate UINT array to CHAR array.
+ *
+ * Parameters:
+ * @param[in, out] *String Pointer to CHAR array
+ * @param[in] *Integer Pointer to UINT array
+ * @param[in] SizeInByte The size of UINT array
+ *
+ * Processing:
+ *
+ */
+VOID
+STATIC
+IntToString (
+ IN OUT CHAR8 *String,
+ IN UINT8 *Integer,
+ IN UINT8 SizeInByte
+ )
+{
+ UINT8 Index;
+
+ for (Index = 0; Index < SizeInByte; Index++) {
+ *(String + Index * 2) = (*(Integer + Index) >> 4) & 0x0F;
+ *(String + Index * 2 + 1) = *(Integer + Index) & 0x0F;
+ }
+ for (Index = 0; Index < (SizeInByte * 2); Index++) {
+ if (*(String + Index) >= 0x0A) {
+ *(String + Index) += 0x37;
+ } else {
+ *(String + Index) += 0x30;
+ }
+ }
+ *(String + SizeInByte * 2) = 0x0;
+}
+
diff --git a/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuFeatureLeveling.c b/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuFeatureLeveling.c
new file mode 100644
index 0000000000..6494c69407
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuFeatureLeveling.c
@@ -0,0 +1,265 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * AMD CPU Feature Leveling Function.
+ *
+ * Contains code to Level the Feature in a multi-socket system
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: CPU
+ * @e \$Revision: 84150 $ @e \$Date: 2012-12-12 15:46:25 -0600 (Wed, 12 Dec 2012) $
+ *
+ */
+/*
+ ******************************************************************************
+ *
+ * Copyright (c) 2008 - 2013, Advanced Micro Devices, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Advanced Micro Devices, Inc. nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ ******************************************************************************
+ *----------------------------------------------------------------------------
+ */
+
+
+/*
+ *----------------------------------------------------------------------------
+ * MODULES USED
+ *
+ *----------------------------------------------------------------------------
+ */
+#include "AGESA.h"
+#include "amdlib.h"
+#include "cpuRegisters.h"
+#include "GeneralServices.h"
+#include "cpuServices.h"
+#include "cpuPostInit.h"
+#include "cpuApicUtilities.h"
+#include "cpuFamilyTranslation.h"
+#include "Filecode.h"
+CODE_GROUP (G1_PEICC)
+RDATA_GROUP (G1_PEICC)
+
+#define FILECODE PROC_CPU_FEATURE_CPUFEATURELEVELING_FILECODE
+/*----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+
+/*----------------------------------------------------------------------------
+ * TYPEDEFS AND STRUCTURES
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------------------
+ * E X P O R T E D F U N C T I O N S
+ *----------------------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * PROTOTYPES OF LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+VOID
+STATIC
+SaveFeatures (
+ IN OUT VOID *cpuFeatureListPtr,
+ IN OUT AMD_CONFIG_PARAMS *StdHeader
+ );
+
+VOID
+STATIC
+WriteFeatures (
+ IN OUT VOID *cpuFeatureListPtr,
+ IN OUT AMD_CONFIG_PARAMS *StdHeader
+ );
+
+VOID
+STATIC
+GetGlobalCpuFeatureListAddress (
+ OUT UINT64 **Address,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ );
+
+/*----------------------------------------------------------------------------------------
+ * P U B L I C F U N C T I O N S
+ *----------------------------------------------------------------------------------------
+ */
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * FeatureLeveling
+ *
+ * CPU feature leveling. Set least common features set of all CPUs
+ *
+ * @param[in,out] StdHeader - Pointer to AMD_CONFIG_PARAMS struct.
+ *
+ */
+VOID
+FeatureLeveling (
+ IN OUT AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ UINT32 BscSocket;
+ UINT32 Ignored;
+ UINT32 BscCoreNum;
+ UINT32 Socket;
+ UINT32 Core;
+ UINT32 NumberOfSockets;
+ UINT32 NumberOfCores;
+ BOOLEAN *FirstTime;
+ BOOLEAN *NeedLeveling;
+ AGESA_STATUS IgnoredSts;
+ CPU_FEATURES_LIST *globalCpuFeatureList;
+ AP_TASK TaskPtr;
+
+ ASSERT (IsBsp (StdHeader, &IgnoredSts));
+
+ GetGlobalCpuFeatureListAddress ((UINT64 **) &globalCpuFeatureList, StdHeader);
+ FirstTime = (BOOLEAN *) ((UINT8 *) globalCpuFeatureList + sizeof (CPU_FEATURES_LIST));
+ NeedLeveling = (BOOLEAN *) ((UINT8 *) globalCpuFeatureList + sizeof (CPU_FEATURES_LIST) + sizeof (BOOLEAN));
+
+ *FirstTime = TRUE;
+ *NeedLeveling = FALSE;
+
+ LibAmdMemFill (globalCpuFeatureList, 0xFF, sizeof (CPU_FEATURES_LIST), StdHeader);
+ IdentifyCore (StdHeader, &BscSocket, &Ignored, &BscCoreNum, &IgnoredSts);
+ NumberOfSockets = GetPlatformNumberOfSockets ();
+
+ TaskPtr.FuncAddress.PfApTaskI = SaveFeatures;
+ TaskPtr.DataTransfer.DataSizeInDwords = SIZE_IN_DWORDS (CPU_FEATURES_LIST);
+ TaskPtr.ExeFlags = WAIT_FOR_CORE;
+ TaskPtr.DataTransfer.DataPtr = globalCpuFeatureList;
+ TaskPtr.DataTransfer.DataTransferFlags = DATA_IN_MEMORY;
+
+ for (Socket = 0; Socket < NumberOfSockets; Socket++) {
+ if (IsProcessorPresent (Socket, StdHeader)) {
+ if (Socket != BscSocket) {
+ ApUtilRunCodeOnSocketCore ((UINT8)Socket, 0, &TaskPtr, StdHeader);
+ }
+ }
+ }
+ ApUtilTaskOnExecutingCore (&TaskPtr, StdHeader, NULL);
+
+ if (*NeedLeveling) {
+ TaskPtr.FuncAddress.PfApTaskI = WriteFeatures;
+ for (Socket = 0; Socket < NumberOfSockets; Socket++) {
+ if (GetActiveCoresInGivenSocket (Socket, &NumberOfCores, StdHeader)) {
+ for (Core = 0; Core < NumberOfCores; Core++) {
+ if ((Socket != BscSocket) || (Core != BscCoreNum)) {
+ ApUtilRunCodeOnSocketCore ((UINT8)Socket, (UINT8)Core, &TaskPtr, StdHeader);
+ }
+ }
+ }
+ }
+ ApUtilTaskOnExecutingCore (&TaskPtr, StdHeader, NULL);
+ }
+}
+
+/*----------------------------------------------------------------------------------------
+ * L O C A L F U N C T I O N S
+ *----------------------------------------------------------------------------------------
+ */
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * SaveFeatures
+ *
+ * save least common features set of all CPUs
+ *
+ * @param[in,out] cpuFeatureListPtr - Pointer to CPU Feature List.
+ * @param[in,out] StdHeader - Pointer to AMD_CONFIG_PARAMS struct.
+ *
+ */
+VOID
+STATIC
+SaveFeatures (
+ IN OUT VOID *cpuFeatureListPtr,
+ IN OUT AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ CPU_SPECIFIC_SERVICES *FamilySpecificServices;
+ FamilySpecificServices = NULL;
+
+ GetCpuServicesOfCurrentCore ((CONST CPU_SPECIFIC_SERVICES **)&FamilySpecificServices, StdHeader);
+ FamilySpecificServices->SaveFeatures (FamilySpecificServices, cpuFeatureListPtr, StdHeader);
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ *
+ * WriteFeatures
+ *
+ * Write out least common features set of all CPUs
+ *
+ * @param[in,out] cpuFeatureListPtr - Pointer to CPU Feature List.
+ * @param[in,out] StdHeader - Pointer to AMD_CONFIG_PARAMS struct.
+ *
+ */
+VOID
+STATIC
+WriteFeatures (
+ IN OUT VOID *cpuFeatureListPtr,
+ IN OUT AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ CPU_SPECIFIC_SERVICES *FamilySpecificServices;
+ FamilySpecificServices = NULL;
+
+ GetCpuServicesOfCurrentCore ((CONST CPU_SPECIFIC_SERVICES **)&FamilySpecificServices, StdHeader);
+ FamilySpecificServices->WriteFeatures (FamilySpecificServices, cpuFeatureListPtr, StdHeader);
+}
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ *
+ * GetGlobalCpuFeatureListAddress
+ *
+ * Determines the address in system DRAM that should be used for CPU feature leveling.
+ *
+ * @param[out] Address Address to utilize
+ * @param[in] StdHeader Config handle for library and services
+ *
+ *
+ */
+VOID
+STATIC
+GetGlobalCpuFeatureListAddress (
+ OUT UINT64 **Address,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ UINT64 AddressValue;
+
+ AddressValue = GLOBAL_CPU_FEATURE_LIST_TEMP_ADDR;
+
+ *Address = (UINT64 *)(UINT32)(AddressValue);
+}
diff --git a/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuFeatures.c b/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuFeatures.c
new file mode 100644
index 0000000000..d3753cb16a
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuFeatures.c
@@ -0,0 +1,283 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * Implement general feature dispatcher.
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: CPU
+ * @e \$Revision: 84150 $ @e \$Date: 2012-12-12 15:46:25 -0600 (Wed, 12 Dec 2012) $
+ *
+ */
+/*
+ ******************************************************************************
+ *
+ * Copyright (c) 2008 - 2013, Advanced Micro Devices, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Advanced Micro Devices, Inc. nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ ******************************************************************************
+ */
+
+/*----------------------------------------------------------------------------------------
+ * M O D U L E S U S E D
+ *----------------------------------------------------------------------------------------
+ */
+#include "AGESA.h"
+#include "amdlib.h"
+#include "Ids.h"
+#include "GeneralServices.h"
+#include "cpuFeatures.h"
+#include "cpuFamilyTranslation.h"
+#include "heapManager.h"
+#include "Filecode.h"
+CODE_GROUP (G1_PEICC)
+RDATA_GROUP (G1_PEICC)
+#define FILECODE PROC_CPU_FEATURE_CPUFEATURES_FILECODE
+/*----------------------------------------------------------------------------------------
+ * D E F I N I T I O N S A N D M A C R O S
+ *----------------------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------------------
+ * T Y P E D E F S A N D S T R U C T U R E S
+ *----------------------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------------------
+ * P R O T O T Y P E S O F L O C A L F U N C T I O N S
+ *----------------------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------------------
+ * E X P O R T E D F U N C T I O N S - External General Services API
+ *----------------------------------------------------------------------------------------
+ */
+extern CONST CPU_FEATURE_DESCRIPTOR* ROMDATA SupportedCpuFeatureList[];
+
+/**
+ * Update the status of a specific feature
+ *
+ * Update the status (is enabled or not) in heap
+ *
+ * @param[in] Feature Indicates the desired feature.
+ * @param[in] IsEnabled Indicates the desired feature
+ * @param[in] StdHeader Standard AMD configuration parameters.
+ *
+ */
+VOID
+UpdateFeatureStatusInHeap (
+ IN DISPATCHABLE_CPU_FEATURES Feature,
+ IN BOOLEAN IsEnabled,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ UINT8 *CpuFeatureIsEnabledHeap;
+ LOCATE_HEAP_PTR LocateHeap;
+
+ ASSERT (Feature < MaxCpuFeature);
+
+ CpuFeatureIsEnabledHeap = NULL;
+ LocateHeap.BufferHandle = AMD_IS_FEATURE_ENABLED;
+ if (HeapLocateBuffer (&LocateHeap, StdHeader) == AGESA_SUCCESS) {
+ CpuFeatureIsEnabledHeap = LocateHeap.BufferPtr;
+ }
+ if (CpuFeatureIsEnabledHeap != NULL) {
+ CpuFeatureIsEnabledHeap[Feature] = (UINT8) IsEnabled;
+ }
+}
+
+/**
+ * Determines if a specific feature is or will be enabled.
+ *
+ * This code traverses the feature list until a match is
+ * found, then invokes the 'IsEnabled' function of the
+ * feature.
+ *
+ * @param[in] Feature Indicates the desired feature.
+ * @param[in] PlatformConfig Contains the runtime modifiable feature input data.
+ * @param[in] StdHeader Standard AMD configuration parameters.
+ *
+ * @retval TRUE Feature is or will be enabled
+ * @retval FALSE Feature is not enabled
+ */
+BOOLEAN
+IsFeatureEnabled (
+ IN DISPATCHABLE_CPU_FEATURES Feature,
+ IN PLATFORM_CONFIGURATION *PlatformConfig,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ UINT8 *CpuFeatureIsEnabledHeap;
+ UINTN i;
+ LOCATE_HEAP_PTR LocateHeap;
+
+ ASSERT (Feature < MaxCpuFeature);
+
+ CpuFeatureIsEnabledHeap = NULL;
+ LocateHeap.BufferHandle = AMD_IS_FEATURE_ENABLED;
+ if (HeapLocateBuffer (&LocateHeap, StdHeader) == AGESA_SUCCESS) {
+ CpuFeatureIsEnabledHeap = LocateHeap.BufferPtr;
+ }
+ if (CpuFeatureIsEnabledHeap != NULL) {
+ if (CpuFeatureIsEnabledHeap[Feature] != CPU_FEATURE_UNDECIDED) {
+ return ((BOOLEAN) CpuFeatureIsEnabledHeap[Feature]);
+ }
+ }
+
+ for (i = 0; SupportedCpuFeatureList[i] != NULL; i++) {
+ if (SupportedCpuFeatureList[i]->Feature == Feature) {
+ return (SupportedCpuFeatureList[i]->IsEnabled (PlatformConfig, StdHeader));
+ }
+ }
+ return FALSE;
+}
+
+/**
+ * Dispatches all features needing to perform some initialization at
+ * this time point.
+ *
+ * This routine searches the feature table for features needing to
+ * run at this time point, and invokes them.
+ *
+ * @param[in] EntryPoint Timepoint designator
+ * @param[in] PlatformConfig Contains the runtime modifiable feature input data.
+ * @param[in] StdHeader Standard AMD configuration parameters.
+ *
+ * @return The most severe status of any called service.
+ */
+AGESA_STATUS
+DispatchCpuFeatures (
+ IN UINT64 EntryPoint,
+ IN PLATFORM_CONFIGURATION *PlatformConfig,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ UINT8 *CpuFeatureIsEnabledHeap;
+ UINTN i;
+ BOOLEAN FeatureIsEnabled;
+ BOOLEAN ResultDecided;
+ AGESA_STATUS AgesaStatus;
+ AGESA_STATUS CalledStatus;
+ AGESA_STATUS IgnoredStatus;
+ LOCATE_HEAP_PTR LocateHeap;
+ ALLOCATE_HEAP_PARAMS AllocateHeap;
+
+
+ AgesaStatus = AGESA_SUCCESS;
+
+ CpuFeatureIsEnabledHeap = NULL;
+ LocateHeap.BufferHandle = AMD_IS_FEATURE_ENABLED;
+ if (HeapLocateBuffer (&LocateHeap, StdHeader) == AGESA_SUCCESS) {
+ CpuFeatureIsEnabledHeap = LocateHeap.BufferPtr;
+ } else {
+ AllocateHeap.BufferHandle = AMD_IS_FEATURE_ENABLED;
+ AllocateHeap.RequestedBufferSize = MaxCpuFeature;
+ AllocateHeap.Persist = HEAP_SYSTEM_MEM;
+ if (HeapAllocateBuffer (&AllocateHeap, StdHeader) == AGESA_SUCCESS) {
+ CpuFeatureIsEnabledHeap = AllocateHeap.BufferPtr;
+ // Initialize all feature as NOT_KNOW_YET
+ LibAmdMemFill ((VOID *) CpuFeatureIsEnabledHeap, CPU_FEATURE_UNDECIDED, MaxCpuFeature, StdHeader);
+ }
+ }
+
+ if (IsBsp (StdHeader, &IgnoredStatus)) {
+ for (i = 0; SupportedCpuFeatureList[i] != NULL; i++) {
+ if ((SupportedCpuFeatureList[i]->EntryPoint & EntryPoint) != 0) {
+ ResultDecided = FALSE;
+ FeatureIsEnabled = FALSE;
+ /// @todo IDS need updated
+ IDS_SKIP_HOOK (IDS_CPU_FEAT, (CPU_FEATURE_DESCRIPTOR *) SupportedCpuFeatureList[i], StdHeader) {
+ if (CpuFeatureIsEnabledHeap != NULL) {
+ // Try to get isFeatureEnabled from heap
+ if (CpuFeatureIsEnabledHeap[SupportedCpuFeatureList[i]->Feature] != CPU_FEATURE_UNDECIDED) {
+ FeatureIsEnabled = (BOOLEAN) (CpuFeatureIsEnabledHeap[SupportedCpuFeatureList[i]->Feature]);
+ ResultDecided = TRUE;
+ }
+ }
+ if (!ResultDecided) {
+ // Get isFeatureEnabled by running IsEnabled
+ FeatureIsEnabled = SupportedCpuFeatureList[i]->IsEnabled (PlatformConfig, StdHeader);
+ if (CpuFeatureIsEnabledHeap != NULL) {
+ CpuFeatureIsEnabledHeap[SupportedCpuFeatureList[i]->Feature] = (UINT8) FeatureIsEnabled;
+ }
+ }
+ if (FeatureIsEnabled) {
+ CalledStatus = SupportedCpuFeatureList[i]->InitializeFeature (EntryPoint, PlatformConfig, StdHeader);
+ if (CalledStatus > AgesaStatus) {
+ AgesaStatus = CalledStatus;
+ }
+ }
+ }
+ }
+ }
+ }
+ return AgesaStatus;
+}
+
+/**
+ * This routine checks whether any non-coherent links in the system
+ * runs in HT1 mode; used to determine whether certain features
+ * should be disabled when this routine returns TRUE.
+ *
+ * @param[in] StdHeader Standard AMD configuration parameters.
+ *
+ * @retval TRUE One of the non-coherent links in the
+ * system runs in HT1 mode
+ * @retval FALSE None of the non-coherent links in the
+ * system is running in HT1 mode
+ */
+BOOLEAN
+IsNonCoherentHt1 (
+ IN AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ UINTN Link;
+ UINT32 Socket;
+ UINT32 Module;
+ PCI_ADDR PciAddress;
+ AGESA_STATUS AgesaStatus;
+ HT_HOST_FEATS HtHostFeats;
+ CPU_SPECIFIC_SERVICES *CpuServices;
+
+ for (Socket = 0; Socket < GetPlatformNumberOfSockets (); Socket++) {
+ if (IsProcessorPresent (Socket, StdHeader)) {
+ GetCpuServicesOfSocket (Socket, (CONST CPU_SPECIFIC_SERVICES **)&CpuServices, StdHeader);
+ for (Module = 0; Module < GetPlatformNumberOfModules (); Module++) {
+ if (GetPciAddress (StdHeader, Socket, Module, &PciAddress, &AgesaStatus)) {
+ HtHostFeats.HtHostValue = 0;
+ Link = 0;
+ while (CpuServices->GetNextHtLinkFeatures (CpuServices, &Link, &PciAddress, &HtHostFeats, StdHeader)) {
+ // Return TRUE and exit routine once we find a non-coherent link in HT1
+ if ((HtHostFeats.HtHostFeatures.NonCoherent == 1) && (HtHostFeats.HtHostFeatures.Ht1 == 1)) {
+ return TRUE;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return FALSE;
+}
diff --git a/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuFeatures.h b/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuFeatures.h
new file mode 100644
index 0000000000..47444ef1ba
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuFeatures.h
@@ -0,0 +1,281 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * Generic CPU feature dispatcher and related services.
+ *
+ * Provides a feature processing engine to handle feature in a
+ * more generic way.
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: Common
+ * @e \$Revision: 84150 $ @e \$Date: 2012-12-12 15:46:25 -0600 (Wed, 12 Dec 2012) $
+ *
+ */
+/*
+ ******************************************************************************
+ *
+ * Copyright (c) 2008 - 2013, Advanced Micro Devices, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Advanced Micro Devices, Inc. nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ ******************************************************************************
+ */
+
+#ifndef _CPU_FEATURES_H_
+#define _CPU_FEATURES_H_
+
+/**
+ * @page cpufeatimpl CPU Generic Feature Implementation Guide
+ *
+ * The CPU generic feature dispatcher provides services which can be used to implement a
+ * wide range of features in a manner that isolates calling code from knowledge about which
+ * families or features are supported in the current build.
+ *
+ * @par Determine if a New Feature is a Suitable Candidate
+ *
+ * A feature must meet the following requirements:
+ * <ul>
+ * <li> Any core in the system must be able to determine if the feature should be enabled or not.
+ *
+ * <ul>
+ * <li> MSRs cannot be read in multisocket systems in the 'IsEnabled' function.
+ *
+ * <li> Cores cannot be launched in the 'IsEnabled' function.
+ * </ul>
+ * </ul>
+ *
+ * @par Determine the Time Point at which the Feature Should be Enabled
+ *
+ * Factors to consider in making this determination:
+ *
+ * <ul>
+ * <li> Determine if there are any dependencies on other settings that require strict ordering.
+ *
+ * <li> Consider the state of the APs that you will need.
+ *
+ * <li> Remember that features enabled during AmdInitEarly will automatically be restored on S3 resume.
+ * </ul>
+ *
+ * @par Implementing a new feature
+ *
+ * Perform the following steps to implement a new feature:
+ *
+ * <ul>
+ * <li> Create a unique equate for your time point, @b if you cannot use an existing time point.
+ *
+ * <li> Create a new value in the DISPATCHABLE_CPU_FEATURES enum for your feature.
+ *
+ * <li> Add a new 'C' file to the Features folder for your feature.
+ *
+ * <ul>
+ * <li> The 'C' file must implement 2 functions -- 'IsEnabled' and 'Initialize'
+ *
+ * <li> The 'C' file must instantiate a CPU_FEATURE_DESCRIPTOR structure.
+ * </ul>
+ *
+ * <li> Add a new 'H' file to the Features folder for your feature.
+ *
+ * <ul>
+ * <li> The 'H' file declares whatever family specific functions required by the feature.
+ *
+ * <li> The 'H' file declares a structure containing all family specific functions. For a reference
+ * example, your feature API should have a set of conventions similar to cpu specific services,
+ * @ref cpuimplfss.
+ * </ul>
+ *
+ * <li> Create 'C' files in all applicable family folders.
+ *
+ * <ul>
+ * <li> Implement the required family specific functions.
+ *
+ * <li> Instantiate a family specific services structure.
+ * </ul>
+ *
+ * <li> Create \<feature name\>Install.h in the include folder.
+ *
+ * <ul>
+ * <li> Add logic to determine when your feature should be included in the build.
+ *
+ * <li> If the feature should be included, define OPTION_\<feature name\> to the address of your
+ * CPU_FEATURE_DESCRIPTOR instantiation. If not, define OPTION_\<feature name\> to be blank.
+ *
+ * <li> Create a family translation table pointing to all applicable instantiations of
+ * family specific function structures.
+ * </ul>
+ *
+ * <li> Modify OptionCpuFeaturesInstall.h in the include folder.
+ *
+ * <ul>
+ * <li> Include \<feature name\>Install.h.
+ *
+ * <li> Add OPTION_\<feature name\> to the SupportedCpuFeatureList array.
+ * </ul>
+ *
+ * <li> If a new time point was created, add a call to DispatchCpuFeatures at the desired location,
+ * passing your new time point equate.
+ * </ul>
+ *
+ */
+
+
+/*----------------------------------------------------------------------------------------
+ * M I X E D (Definitions And Macros / Typedefs, Structures, Enums)
+ *----------------------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------------------
+ * D E F I N I T I O N S A N D M A C R O S
+ *----------------------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------------------
+ * T Y P E D E F S, S T R U C T U R E S, E N U M S
+ *----------------------------------------------------------------------------------------
+ */
+#define CPU_FEAT_BEFORE_PM_INIT (0x0000000000000001ull)
+#define CPU_FEAT_AFTER_PM_INIT (0x0000000000000002ull)
+#define CPU_FEAT_AFTER_POST_MTRR_SYNC (0x0000000000000004ull)
+#define CPU_FEAT_INIT_MID_END (0x0000000000000008ull)
+#define CPU_FEAT_INIT_LATE_END (0x0000000000000010ull)
+#define CPU_FEAT_S3_LATE_RESTORE_END (0x0000000000000020ull)
+#define CPU_FEAT_AFTER_RESUME_MTRR_SYNC (0x0000000000000040ull)
+#define CPU_FEAT_AFTER_COHERENT_DISCOVERY (0x0000000000000080ull)
+#define CPU_FEAT_BEFORE_RELINQUISH_AP (0x0000000000000100ull)
+
+#define CPU_FEATURE_UNDECIDED 0xFFul
+#define CPU_FEATURE_DISABLED ((UINT8) FALSE)
+#define CPU_FEATURE_ENABLED ((UINT8) TRUE)
+
+/**
+ * Enumerated list of supported features.
+ */
+typedef enum {
+ L3Features, ///< L3 dependent features
+ MsgBasedC1e, ///< Message-based C1e
+ CoreLeveling, ///< Core Leveling
+ C6Cstate, ///< C6 C-state
+ IoCstate, ///< IO C-state
+ CacheFlushOnHalt, ///< Cache Flush On Halt
+ PreserveAroundMailbox, ///< Save-Restore the registers used for AP mailbox, to preserve their normal function.
+ CpuApm, ///< Application Power Management
+ CoreBoost, ///< Core Performance Boost (CPB)
+ LowPwrPstate, ///< 500 MHz Low Power P-state
+ PstateHpcMode, ///< High performance computing mode
+ CpuPsi, ///< Power Status Indicator
+ CpuHtc, ///< Hardware Thermal Control
+ CpuTdpLimiting, ///< TDP limiting
+ PrefetchMode, ///< CPU Prefetch Mode
+ MaxCpuFeature ///< Not a valid value, used for verifying input
+} DISPATCHABLE_CPU_FEATURES;
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * Feature specific call to check if it is supported by the system.
+ *
+ * @param[in] PlatformConfig Contains the runtime modifiable feature input data.
+ * @param[in] StdHeader Config Handle for library, services.
+ *
+ * @retval TRUE Feature is supported.
+ * @retval FALSE Feature is not supported.
+ *
+ */
+typedef BOOLEAN F_CPU_FEATURE_IS_ENABLED (
+ IN PLATFORM_CONFIGURATION *PlatformConfig,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ );
+
+/// Reference to a Method.
+typedef F_CPU_FEATURE_IS_ENABLED *PF_CPU_FEATURE_IS_ENABLED;
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * The feature's main entry point for enablement.
+ *
+ * @param[in] EntryPoint Timepoint designator.
+ * @param[in] PlatformConfig Contains the runtime modifiable feature input data.
+ * @param[in] StdHeader Config Handle for library, services.
+ *
+ * @return Family specific error value.
+ *
+ */
+typedef AGESA_STATUS F_CPU_FEATURE_INITIALIZE (
+ IN UINT64 EntryPoint,
+ IN PLATFORM_CONFIGURATION *PlatformConfig,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ );
+
+/// Reference to a Method.
+typedef F_CPU_FEATURE_INITIALIZE *PF_CPU_FEATURE_INITIALIZE;
+
+
+/**
+ * Generic feature descriptor
+ */
+typedef struct {
+ DISPATCHABLE_CPU_FEATURES Feature; ///< Enumerated feature ID
+ UINT64 EntryPoint; ///< Timepoint designator
+ PF_CPU_FEATURE_IS_ENABLED IsEnabled; ///< Pointer to the function that checks if the feature is supported
+ PF_CPU_FEATURE_INITIALIZE InitializeFeature; ///< Pointer to the function that enables the feature
+} CPU_FEATURE_DESCRIPTOR;
+
+/**
+ * Table descriptor for the installed features.
+ */
+typedef struct {
+ UINT8 NumberOfFeats; ///< Number of valid entries in the table.
+ CPU_FEATURE_DESCRIPTOR *FeatureList; ///< Pointer to the first element in the array.
+} CPU_FEATURE_TABLE;
+
+/*----------------------------------------------------------------------------------------
+ * F U N C T I O N P R O T O T Y P E
+ *----------------------------------------------------------------------------------------
+ */
+VOID
+UpdateFeatureStatusInHeap (
+ IN DISPATCHABLE_CPU_FEATURES Feature,
+ IN BOOLEAN IsEnabled,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ );
+
+BOOLEAN
+IsFeatureEnabled (
+ IN DISPATCHABLE_CPU_FEATURES Feature,
+ IN PLATFORM_CONFIGURATION *PlatformConfig,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ );
+
+AGESA_STATUS
+DispatchCpuFeatures (
+ IN UINT64 EntryPoint,
+ IN PLATFORM_CONFIGURATION *PlatformConfig,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ );
+
+BOOLEAN
+IsNonCoherentHt1 (
+ IN AMD_CONFIG_PARAMS *StdHeader
+ );
+
+#endif // _CPU_FEATURES_H_
diff --git a/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuHtc.c b/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuHtc.c
new file mode 100644
index 0000000000..9807102fe3
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuHtc.c
@@ -0,0 +1,201 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * AMD AGESA CPU Hardware Thermal Control (HTC) feature support code.
+ *
+ * Contains code that declares the AGESA CPU HTC related APIs
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: CPU/Feature
+ * @e \$Revision: 84150 $ @e \$Date: 2012-12-12 15:46:25 -0600 (Wed, 12 Dec 2012) $
+ *
+ */
+/*
+ ******************************************************************************
+ *
+ * Copyright (c) 2008 - 2013, Advanced Micro Devices, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Advanced Micro Devices, Inc. nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ ******************************************************************************
+ */
+
+/*----------------------------------------------------------------------------------------
+ * M O D U L E S U S E D
+ *----------------------------------------------------------------------------------------
+ */
+#include "AGESA.h"
+#include "GeneralServices.h"
+#include "cpuFamilyTranslation.h"
+#include "cpuApicUtilities.h"
+#include "cpuFeatures.h"
+#include "cpuHtc.h"
+#include "OptionMultiSocket.h"
+#include "Filecode.h"
+CODE_GROUP (G1_PEICC)
+RDATA_GROUP (G1_PEICC)
+
+#define FILECODE PROC_CPU_FEATURE_CPUHTC_FILECODE
+
+/*----------------------------------------------------------------------------------------
+ * D E F I N I T I O N S A N D M A C R O S
+ *----------------------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------------------
+ * T Y P E D E F S A N D S T R U C T U R E S
+ *----------------------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------------------
+ * P R O T O T Y P E S O F L O C A L F U N C T I O N S
+ *----------------------------------------------------------------------------------------
+ */
+UINT32
+STATIC
+EnableHtcOnSocket (
+ IN VOID *EntryPoint,
+ IN AMD_CONFIG_PARAMS *StdHeader,
+ IN AMD_CPU_EARLY_PARAMS *CpuEarlyParams
+ );
+
+/*----------------------------------------------------------------------------------------
+ * E X P O R T E D F U N C T I O N S
+ *----------------------------------------------------------------------------------------
+ */
+extern CPU_FAMILY_SUPPORT_TABLE HtcFamilyServiceTable;
+extern OPTION_MULTISOCKET_CONFIGURATION OptionMultiSocketConfiguration;
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * Should Hardware Thermal Control (HTC) be enabled
+ *
+ * @param[in] PlatformConfig Contains the runtime modifiable feature input data.
+ * @param[in] StdHeader Config Handle for library, services.
+ *
+ * @retval TRUE HTC is supported.
+ * @retval FALSE HTC cannot be enabled.
+ *
+ */
+BOOLEAN
+STATIC
+IsHtcFeatureEnabled (
+ IN PLATFORM_CONFIGURATION *PlatformConfig,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ UINT32 Socket;
+ BOOLEAN IsEnabled;
+ HTC_FAMILY_SERVICES *HtcFamilyServices;
+
+ IsEnabled = TRUE;
+
+ for (Socket = 0; Socket < GetPlatformNumberOfSockets (); Socket++) {
+ if (IsProcessorPresent (Socket, StdHeader)) {
+ GetFeatureServicesOfSocket (&HtcFamilyServiceTable, Socket, (CONST VOID **)&HtcFamilyServices, StdHeader);
+ if ((HtcFamilyServices == NULL) || (!HtcFamilyServices->IsHtcSupported (HtcFamilyServices, Socket, PlatformConfig, StdHeader))) {
+ IsEnabled = FALSE;
+ break;
+ }
+ }
+ }
+ return IsEnabled;
+}
+
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * Enable Hardware Thermal Control (HTC)
+ *
+ * @param[in] EntryPoint Timepoint designator.
+ * @param[in] PlatformConfig Contains the runtime modifiable feature input data.
+ * @param[in] StdHeader Config Handle for library, services.
+ *
+ * @retval AGESA_SUCCESS Always succeeds.
+ *
+ */
+AGESA_STATUS
+STATIC
+InitializeHtcFeature (
+ IN UINT64 EntryPoint,
+ IN PLATFORM_CONFIGURATION *PlatformConfig,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ AP_TASK TaskPtr;
+ AGESA_STATUS AgesaStatus;
+ AMD_CPU_EARLY_PARAMS CpuEarlyParams;
+
+ IDS_HDT_CONSOLE (CPU_TRACE, " HTC is being initialized\n");
+
+ CpuEarlyParams.PlatformConfig = *PlatformConfig;
+
+ TaskPtr.FuncAddress.PfApTaskIOC = EnableHtcOnSocket;
+ TaskPtr.DataTransfer.DataSizeInDwords = 2;
+ TaskPtr.DataTransfer.DataPtr = &EntryPoint;
+ TaskPtr.DataTransfer.DataTransferFlags = 0;
+ TaskPtr.ExeFlags = PASS_EARLY_PARAMS | TASK_HAS_OUTPUT;
+ AgesaStatus = OptionMultiSocketConfiguration.BscRunCodeOnAllSystemCore0s (&TaskPtr, StdHeader, &CpuEarlyParams);
+
+ IDS_HDT_CONSOLE (CPU_TRACE, " HTC is enabled\n");
+
+ return AgesaStatus;
+}
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * AP task to enable HTC
+ *
+ * @param[in] EntryPoint Timepoint designator.
+ * @param[in] StdHeader Config Handle for library, services.
+ * @param[in] CpuEarlyParams Service parameters.
+ *
+ */
+UINT32
+STATIC
+EnableHtcOnSocket (
+ IN VOID *EntryPoint,
+ IN AMD_CONFIG_PARAMS *StdHeader,
+ IN AMD_CPU_EARLY_PARAMS *CpuEarlyParams
+ )
+{
+ AGESA_STATUS CalledStatus;
+ HTC_FAMILY_SERVICES *HtcFamilyServices;
+
+ CalledStatus = AGESA_UNSUPPORTED;
+ GetFeatureServicesOfCurrentCore (&HtcFamilyServiceTable, (CONST VOID **)&HtcFamilyServices, StdHeader);
+ if (HtcFamilyServices != NULL) {
+ CalledStatus = HtcFamilyServices->EnableHtcOnSocket (HtcFamilyServices, *((UINT64 *) EntryPoint), &CpuEarlyParams->PlatformConfig, StdHeader);
+ }
+ return (UINT32) CalledStatus;
+}
+
+CONST CPU_FEATURE_DESCRIPTOR ROMDATA CpuFeatureHtc =
+{
+ CpuHtc,
+ (CPU_FEAT_AFTER_POST_MTRR_SYNC | CPU_FEAT_AFTER_RESUME_MTRR_SYNC),
+ IsHtcFeatureEnabled,
+ InitializeHtcFeature
+};
diff --git a/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuHtc.h b/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuHtc.h
new file mode 100644
index 0000000000..913802f8e9
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuHtc.h
@@ -0,0 +1,130 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * AMD AGESA CPU Hardware Thermal Control (HTC) Functions declarations.
+ *
+ * Contains code that declares the AGESA CPU HTC related APIs
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: CPU/Feature
+ * @e \$Revision: 84150 $ @e \$Date: 2012-12-12 15:46:25 -0600 (Wed, 12 Dec 2012) $
+ *
+ */
+/*
+ ******************************************************************************
+ *
+ * Copyright (c) 2008 - 2013, Advanced Micro Devices, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Advanced Micro Devices, Inc. nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ ******************************************************************************
+ */
+
+#ifndef _CPU_HTC_H_
+#define _CPU_HTC_H_
+
+/*----------------------------------------------------------------------------------------
+ * M I X E D (Definitions And Macros / Typedefs, Structures, Enums)
+ *----------------------------------------------------------------------------------------
+ */
+// Forward declaration needed for multi-structure mutual references
+AGESA_FORWARD_DECLARATION (HTC_FAMILY_SERVICES);
+
+/*----------------------------------------------------------------------------------------
+ * D E F I N I T I O N S A N D M A C R O S
+ *----------------------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------------------
+ * T Y P E D E F S A N D S T R U C T U R E S
+ *----------------------------------------------------------------------------------------
+ */
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * Family specific call to check if Hardware Thermal Control (HTC) is supported.
+ *
+ * @param[in] HtcServices HTC services.
+ * @param[in] Socket Zero-based socket number.
+ * @param[in] PlatformConfig Contains the runtime modifiable feature input data.
+ * @param[in] StdHeader Config Handle for library, services.
+ *
+ * @retval TRUE HTC is supported.
+ * @retval FALSE HTC is not supported.
+ *
+ */
+typedef BOOLEAN F_HTC_IS_SUPPORTED (
+ IN HTC_FAMILY_SERVICES *HtcServices,
+ IN UINT32 Socket,
+ IN PLATFORM_CONFIGURATION *PlatformConfig,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ );
+
+/// Reference to a Method.
+typedef F_HTC_IS_SUPPORTED *PF_HTC_IS_SUPPORTED;
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * Family specific call to enable HTC.
+ *
+ * @param[in] HtcServices HTC services.
+ * @param[in] EntryPoint Timepoint designator.
+ * @param[in] PlatformConfig Contains the runtime modifiable feature input data.
+ * @param[in] StdHeader Config Handle for library, services.
+ *
+ * @return Family specific error value.
+ *
+ */
+typedef AGESA_STATUS F_HTC_INIT (
+ IN HTC_FAMILY_SERVICES *HtcServices,
+ IN UINT64 EntryPoint,
+ IN PLATFORM_CONFIGURATION *PlatformConfig,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ );
+
+/// Reference to a Method.
+typedef F_HTC_INIT *PF_HTC_INIT;
+
+/**
+ * Provide the interface to the HTC Family Specific Services.
+ *
+ * Use the methods or data in this struct to adapt the feature code to a specific cpu family or model (or stepping!).
+ * Each supported Family must provide an implementation for all methods in this interface, even if the
+ * implementation is a CommonReturn().
+ */
+typedef struct _HTC_FAMILY_SERVICES {
+ UINT16 Revision; ///< Interface version
+ // Public Methods.
+ PF_HTC_IS_SUPPORTED IsHtcSupported; ///< Method: Family specific call to check if HTC is supported.
+ PF_HTC_INIT EnableHtcOnSocket; ///< Method: Family specific call to enable HTC.
+} HTC_FAMILY_SERVICES;
+
+
+/*----------------------------------------------------------------------------------------
+ * F U N C T I O N S P R O T O T Y P E
+ *----------------------------------------------------------------------------------------
+ */
+
+#endif // _CPU_HTC_H_
diff --git a/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuIoCstate.c b/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuIoCstate.c
new file mode 100644
index 0000000000..a98f1823b1
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuIoCstate.c
@@ -0,0 +1,207 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * AMD AGESA CPU IO Cstate function declarations.
+ *
+ * Contains code that declares the AGESA CPU IO Cstate related APIs
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: CPU/Feature
+ * @e \$Revision: 84150 $ @e \$Date: 2012-12-12 15:46:25 -0600 (Wed, 12 Dec 2012) $
+ */
+/*
+ ******************************************************************************
+ *
+ * Copyright (c) 2008 - 2013, Advanced Micro Devices, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Advanced Micro Devices, Inc. nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ ******************************************************************************
+ */
+
+/*----------------------------------------------------------------------------------------
+ * M O D U L E S U S E D
+ *----------------------------------------------------------------------------------------
+ */
+
+#include "AGESA.h"
+#include "amdlib.h"
+#include "cpuFeatures.h"
+#include "cpuIoCstate.h"
+#include "cpuServices.h"
+#include "cpuFamilyTranslation.h"
+#include "cpuApicUtilities.h"
+#include "OptionMultiSocket.h"
+#include "Filecode.h"
+CODE_GROUP (G1_PEICC)
+RDATA_GROUP (G1_PEICC)
+
+#define FILECODE PROC_CPU_FEATURE_CPUIOCSTATE_FILECODE
+
+/*----------------------------------------------------------------------------------------
+ * D E F I N I T I O N S A N D M A C R O S
+ *----------------------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------------------
+ * T Y P E D E F S A N D S T R U C T U R E S
+ *----------------------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------------------
+ * P R O T O T Y P E S O F L O C A L F U N C T I O N S
+ *----------------------------------------------------------------------------------------
+ */
+
+VOID
+STATIC
+EnableIoCstateOnSocket (
+ IN VOID *EntryPoint,
+ IN AMD_CONFIG_PARAMS *StdHeader,
+ IN AMD_CPU_EARLY_PARAMS *CpuEarlyParams
+ );
+/*----------------------------------------------------------------------------------------
+ * E X P O R T E D F U N C T I O N S
+ *----------------------------------------------------------------------------------------
+ */
+extern CPU_FAMILY_SUPPORT_TABLE IoCstateFamilyServiceTable;
+extern OPTION_MULTISOCKET_CONFIGURATION OptionMultiSocketConfiguration;
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * Should IO Cstate be enabled
+ * If all processors support IO Cstate, return TRUE. Otherwise, return FALSE
+ *
+ * @param[in] PlatformConfig Contains the runtime modifiable feature input data.
+ * @param[in] StdHeader Config Handle for library, services.
+ *
+ * @retval TRUE IO Cstate is supported.
+ * @retval FALSE IO Cstate cannot be enabled.
+ *
+ */
+BOOLEAN
+STATIC
+IsIoCstateFeatureSupported (
+ IN PLATFORM_CONFIGURATION *PlatformConfig,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ UINT32 Socket;
+ BOOLEAN IsSupported;
+ IO_CSTATE_FAMILY_SERVICES *IoCstateServices;
+
+ IsSupported = FALSE;
+ if ((PlatformConfig->CStateIoBaseAddress != 0) && (PlatformConfig->CStateIoBaseAddress <= 0xFFF8)) {
+ for (Socket = 0; Socket < GetPlatformNumberOfSockets (); Socket++) {
+ if (IsProcessorPresent (Socket, StdHeader)) {
+ GetFeatureServicesOfSocket (&IoCstateFamilyServiceTable, Socket, (CONST VOID **)&IoCstateServices, StdHeader);
+ if (IoCstateServices != NULL) {
+ if (IoCstateServices->IsIoCstateSupported (IoCstateServices, Socket, StdHeader)) {
+ IsSupported = TRUE;
+ } else {
+ // Stop checking remaining socket(s) once we find one that does not support IO Cstates
+ IsSupported = FALSE;
+ break;
+ }
+ } else {
+ // Exit the for loop if we found a socket that does not have the IO Cstates feature installed
+ IsSupported = FALSE;
+ break;
+ }
+ }
+ }
+ }
+ return IsSupported;
+}
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * Enable IO Cstate feature
+ *
+ * @param[in] EntryPoint Timepoint designator.
+ * @param[in] PlatformConfig Contains the runtime modifiable feature input data.
+ * @param[in] StdHeader Config Handle for library, services.
+ *
+ * @retval AGESA_SUCCESS Always succeeds.
+ *
+ */
+AGESA_STATUS
+STATIC
+InitializeIoCstateFeature (
+ IN UINT64 EntryPoint,
+ IN PLATFORM_CONFIGURATION *PlatformConfig,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ AP_TASK TaskPtr;
+ AMD_CPU_EARLY_PARAMS CpuEarlyParams;
+
+ IDS_HDT_CONSOLE (CPU_TRACE, " IO C-state is enabled\n");
+
+ CpuEarlyParams.PlatformConfig = *PlatformConfig;
+
+ TaskPtr.FuncAddress.PfApTaskIC = EnableIoCstateOnSocket;
+ TaskPtr.DataTransfer.DataSizeInDwords = 2;
+ TaskPtr.DataTransfer.DataPtr = &EntryPoint;
+ TaskPtr.DataTransfer.DataTransferFlags = 0;
+ TaskPtr.ExeFlags = PASS_EARLY_PARAMS;
+ OptionMultiSocketConfiguration.BscRunCodeOnAllSystemCore0s (&TaskPtr, StdHeader, &CpuEarlyParams);
+
+ return AGESA_SUCCESS;
+}
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * 'Local' core 0 task to enable IO Cstate on it's socket.
+ *
+ * @param[in] EntryPoint Timepoint designator.
+ * @param[in] StdHeader Config Handle for library, services.
+ * @param[in] CpuEarlyParams Service parameters.
+ *
+ */
+VOID
+STATIC
+EnableIoCstateOnSocket (
+ IN VOID *EntryPoint,
+ IN AMD_CONFIG_PARAMS *StdHeader,
+ IN AMD_CPU_EARLY_PARAMS *CpuEarlyParams
+ )
+{
+ IO_CSTATE_FAMILY_SERVICES *FamilyServices;
+
+ GetFeatureServicesOfCurrentCore (&IoCstateFamilyServiceTable, (CONST VOID **)&FamilyServices, StdHeader);
+ FamilyServices->InitializeIoCstate (FamilyServices,
+ *((UINT64 *) EntryPoint),
+ &CpuEarlyParams->PlatformConfig,
+ StdHeader);
+}
+
+CONST CPU_FEATURE_DESCRIPTOR ROMDATA CpuFeatureIoCstate =
+{
+ IoCstate,
+ (CPU_FEAT_AFTER_PM_INIT),
+ IsIoCstateFeatureSupported,
+ InitializeIoCstateFeature
+};
diff --git a/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuIoCstate.h b/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuIoCstate.h
new file mode 100644
index 0000000000..5cd9c823b4
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuIoCstate.h
@@ -0,0 +1,283 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * AMD AGESA CPU IO Cstate feature support code.
+ *
+ * Contains code that declares the AGESA CPU IO Cstate related APIs
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: CPU/Feature
+ * @e \$Revision: 84150 $ @e \$Date: 2012-12-12 15:46:25 -0600 (Wed, 12 Dec 2012) $
+ */
+/*
+ ******************************************************************************
+ *
+ * Copyright (c) 2008 - 2013, Advanced Micro Devices, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Advanced Micro Devices, Inc. nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ ******************************************************************************
+ */
+
+#ifndef _CPU_IO_CSTATE_H_
+#define _CPU_IO_CSTATE_H_
+
+/*----------------------------------------------------------------------------------------
+ * M I X E D (Definitions And Macros / Typedefs, Structures, Enums)
+ *----------------------------------------------------------------------------------------
+ */
+// Forward declaration needed for multi-structure mutual references
+AGESA_FORWARD_DECLARATION (IO_CSTATE_FAMILY_SERVICES);
+
+/*----------------------------------------------------------------------------------------
+ * D E F I N I T I O N S A N D M A C R O S
+ *----------------------------------------------------------------------------------------
+ */
+// Defines for ACPI C-State Objects
+#define CST_NAME__ '_'
+#define CST_NAME_C 'C'
+#define CST_NAME_S 'S'
+#define CST_NAME_T 'T'
+#define CST_LENGTH (CST_BODY_SIZE - 1)
+#define CST_NUM_OF_ELEMENTS 0x02
+#define CST_COUNT 0x01
+#define CST_PKG_LENGTH (CST_BODY_SIZE - 6) // CST_BODY_SIZE - PkgHeader - Count Buffer
+#define CST_PKG_ELEMENTS 0x04
+#define CST_SUBPKG_LENGTH 0x14
+#define CST_SUBPKG_ELEMENTS 0x0A
+#define CST_GDR_LENGTH 0x000C
+#define CST_C1_TYPE 0x01
+#define CST_C2_TYPE 0x02
+
+#define CSD_NAME_D 'D'
+#define CSD_COORD_TYPE_HW_ALL 0xFE
+
+/*----------------------------------------------------------------------------------------
+ * T Y P E D E F S A N D S T R U C T U R E S
+ *----------------------------------------------------------------------------------------
+ */
+/* AML code definition */
+
+/// CST Header
+typedef struct _CST_HEADER_STRUCT {
+ UINT8 NameOpcode; ///< Name Opcode
+ UINT8 CstName_a__; ///< String "_"
+ UINT8 CstName_a_C; ///< String "C"
+ UINT8 CstName_a_S; ///< String "S"
+ UINT8 CstName_a_T; ///< String "T"
+} CST_HEADER_STRUCT;
+#define CST_HEADER_SIZE 5
+
+/// CST Body
+typedef struct _CST_BODY_STRUCT {
+ UINT8 PkgOpcode; ///< Package Opcode
+ UINT8 PkgLength; ///< Package Length
+ UINT8 PkgElements; ///< Number of Elements
+ UINT8 BytePrefix; ///< Byte Prefix Opcode
+ UINT8 Count; ///< Number of Cstate info packages
+ UINT8 PkgOpcode2; ///< Package Opcode
+ UINT8 PkgLength2; ///< Package Length
+ UINT8 PkgElements2; ///< Number of Elements
+ UINT8 BufferOpcode; ///< Buffer Opcode
+ UINT8 BufferLength; ///< Buffer Length
+ UINT8 BufferElements; ///< Number of Elements
+ UINT8 BufferOpcode2; ///< Buffer Opcode
+ UINT8 GdrOpcode; ///< Generic Register Descriptor Opcode
+ UINT16 GdrLength; ///< Descriptor Length
+ UINT8 AddrSpaceId; ///< Address Space ID
+ UINT8 RegBitWidth; ///< Register Bit Width
+ UINT8 RegBitOffset; ///< Register Bit Offset
+ UINT8 AddressSize; ///< Address Size
+ UINT64 RegisterAddr; ///< Register Address
+ UINT16 EndTag; ///< End Tag Descriptor
+ UINT8 BytePrefix2; ///< Byte Prefix Opcode
+ UINT8 Type; ///< Type
+ UINT8 WordPrefix; ///< Word Prefix Opcode
+ UINT16 Latency; ///< Latency
+ UINT8 DWordPrefix; ///< Dword Prefix Opcode
+ UINT32 Power; ///< Power
+} CST_BODY_STRUCT;
+#define CST_BODY_SIZE 39
+
+/// CSD Header
+typedef struct _CSD_HEADER_STRUCT {
+ UINT8 NameOpcode; ///< Name Opcode
+ UINT8 CsdName_a__; ///< String "_"
+ UINT8 CsdName_a_C; ///< String "C"
+ UINT8 CsdName_a_S; ///< String "S"
+ UINT8 CsdName_a_D; ///< String "D"
+} CSD_HEADER_STRUCT;
+#define CSD_HEADER_SIZE 5
+
+/// CSD Body
+typedef struct _CSD_BODY_STRUCT {
+ UINT8 PkgOpcode; ///< Package Opcode
+ UINT8 PkgLength; ///< Package Length
+ UINT8 PkgElements; ///< Number of Elements
+ UINT8 PkgOpcode2; ///< Package Opcode
+ UINT8 PkgLength2; ///< Package Length
+ UINT8 PkgElements2; ///< Number of Elements
+ UINT8 BytePrefix; ///< Byte Prefix Opcode
+ UINT8 NumEntries; ///< Number of Entries
+ UINT8 BytePrefix2; ///< Byte Prefix Opcode
+ UINT8 Revision; ///< Revision
+ UINT8 DWordPrefix; ///< DWord Prefix Opcode
+ UINT32 Domain; ///< Dependency Domain Number
+ UINT8 DWordPrefix2; ///< DWord Prefix Opcode
+ UINT32 CoordType; ///< Coordination Type
+ UINT8 DWordPrefix3; ///< Dword Prefix Opcode
+ UINT32 NumProcessors; ///< Number of Processors in the Domain
+ UINT8 DWordPrefix4; ///< Dword Prefix Opcode
+ UINT32 Index; ///< Index of C-State entry for which dependency applies
+} CSD_BODY_STRUCT;
+#define CSD_BODY_SIZE 30
+
+/// input for create _CST
+typedef struct _ACPI_CST_CREATE_INPUT {
+ IO_CSTATE_FAMILY_SERVICES *IoCstateServices; ///< Family service of IoCstate
+ UINT8 LocalApicId; ///< Local Apic for create _CST
+ VOID **PstateAcpiBufferPtr; ///< buffer for fill _CST
+} ACPI_CST_CREATE_INPUT ;
+
+/// input for get _CST
+typedef struct _ACPI_CST_GET_INPUT {
+ IO_CSTATE_FAMILY_SERVICES *IoCstateServices; ///< Family service of IoCstate
+ PLATFORM_CONFIGURATION *PlatformConfig; ///< platform config
+ UINT32 *CStateAcpiObjSizePtr; ///< Point to size of _CST
+} ACPI_CST_GET_INPUT ;
+
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * Family specific call to check if IO Cstate is supported.
+ *
+ * @param[in] IoCstateServices IO Cstate services.
+ * @param[in] Socket Zero-based socket number.
+ * @param[in] StdHeader Config Handle for library, services.
+ *
+ * @retval TRUE IO Cstate is supported.
+ * @retval FALSE IO Cstate is not supported.
+ *
+ */
+typedef BOOLEAN F_IO_CSTATE_IS_SUPPORTED (
+ IN IO_CSTATE_FAMILY_SERVICES *IoCstateServices,
+ IN UINT32 Socket,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ );
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * Family specific call to enable IO Cstate.
+ *
+ * @param[in] IoCstateServices IO Cstate services.
+ * @param[in] EntryPoint Timepoint designator.
+ * @param[in] PlatformConfig Contains the runtime modifiable feature input data.
+ * @param[in] StdHeader Config Handle for library, services.
+ *
+ * @return Family specific error value.
+ *
+ */
+typedef AGESA_STATUS F_IO_CSTATE_INIT (
+ IN IO_CSTATE_FAMILY_SERVICES *IoCstateServices,
+ IN UINT64 EntryPoint,
+ IN PLATFORM_CONFIGURATION *PlatformConfig,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ );
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * Family specific call to return the size of ACPI C-State Objects
+ *
+ * @param[in] IoCstateServices IO Cstate services.
+ * @param[in] PlatformConfig Contains the runtime modifiable feature input data
+ * @param[in] StdHeader Config Handle for library, services.
+ *
+ * @retval Size of ACPI C-State Objects
+ *
+ */
+typedef UINT32 F_IO_CSTATE_GET_CST_SIZE (
+ IN IO_CSTATE_FAMILY_SERVICES *IoCstateServices,
+ IN PLATFORM_CONFIGURATION *PlatformConfig,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ );
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * Family specific call to create ACPI C-State Objects
+ *
+ * @param[in] IoCstateServices IO Cstate services.
+ * @param[in] LocalApicId Local Apic Id
+ * @param[in, out] PstateAcpiBufferPtr Pointer to Pstate data buffer
+ * @param[in] StdHeader Config Handle for library, services.
+ *
+ */
+typedef VOID F_IO_CSTATE_CREATE_CST (
+ IN IO_CSTATE_FAMILY_SERVICES *IoCstateServices,
+ IN UINT8 LocalApicId,
+ IN OUT VOID **PstateAcpiBufferPtr,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ );
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * Family specific call to check whether CSD object should be created.
+ *
+ * @param[in] IoCstateServices IO Cstate services.
+ * @param[in] StdHeader Config Handle for library, services.
+ *
+ * @retval TRUE CSD Object should be created.
+ * @retval FALSE CSD Object should not be created.
+ *
+ */
+typedef BOOLEAN F_IO_CSTATE_IS_CSD_GENERATED (
+ IN IO_CSTATE_FAMILY_SERVICES *IoCstateServices,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ );
+
+/// Reference to a Method
+typedef F_IO_CSTATE_IS_SUPPORTED *PF_IO_CSTATE_IS_SUPPORTED;
+typedef F_IO_CSTATE_INIT *PF_IO_CSTATE_INIT;
+typedef F_IO_CSTATE_GET_CST_SIZE *PF_IO_CSTATE_GET_CST_SIZE;
+typedef F_IO_CSTATE_CREATE_CST *PF_IO_CSTATE_CREATE_CST;
+typedef F_IO_CSTATE_IS_CSD_GENERATED *PF_IO_CSTATE_IS_CSD_GENERATED;
+
+/**
+ * Provide the interface to the IO Cstate Family Specific Services.
+ *
+ * Use the methods or data in this struct to adapt the feature code to a specific cpu family or model (or stepping!).
+ * Each supported Family must provide an implementation for all methods in this interface, even if the
+ * implementation is a CommonReturn().
+ */
+struct _IO_CSTATE_FAMILY_SERVICES {
+ UINT16 Revision; ///< Interface version
+ // Public Methods.
+ PF_IO_CSTATE_IS_SUPPORTED IsIoCstateSupported; ///< Method: Family specific call to check if IO Cstate is supported.
+ PF_IO_CSTATE_INIT InitializeIoCstate; ///< Method: Family specific call to enable IO Cstate
+ PF_IO_CSTATE_GET_CST_SIZE GetAcpiCstObj; ///< Method: Family specific call to return the size of ACPI CST objects.
+ PF_IO_CSTATE_CREATE_CST CreateAcpiCstObj; ///< Method: Family specific call to create ACPI CST object
+ PF_IO_CSTATE_IS_CSD_GENERATED IsCsdObjGenerated; ///< Method: Family specific call to check whether CSD Object should be created.
+};
+
+#endif // _CPU_IO_CSTATE_H_
diff --git a/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuL3Features.h b/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuL3Features.h
new file mode 100644
index 0000000000..d2c1424f12
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuL3Features.h
@@ -0,0 +1,399 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * AMD CPU L3 Features Initialization functions.
+ *
+ * Contains code that declares the AGESA CPU L3 dependent feature related APIs
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: CPU/Feature
+ * @e \$Revision: 84150 $ @e \$Date: 2012-12-12 15:46:25 -0600 (Wed, 12 Dec 2012) $
+ *
+ */
+/*
+ ******************************************************************************
+ *
+ * Copyright (c) 2008 - 2013, Advanced Micro Devices, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Advanced Micro Devices, Inc. nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ ******************************************************************************
+ */
+
+#ifndef _CPU_L3_FEATURES_H_
+#define _CPU_L3_FEATIRES_H_
+
+#include "Filecode.h"
+/*----------------------------------------------------------------------------------------
+ * M I X E D (Definitions And Macros / Typedefs, Structures, Enums)
+ *----------------------------------------------------------------------------------------
+ */
+// Forward declaration needed for multi-structure mutual references
+AGESA_FORWARD_DECLARATION (L3_FEATURE_FAMILY_SERVICES);
+
+/*----------------------------------------------------------------------------------------
+ * D E F I N I T I O N S A N D M A C R O S
+ *----------------------------------------------------------------------------------------
+ */
+#define AP_LATE_TASK_DISABLE_CACHE (0x00000000ul | PROC_CPU_FEATURE_CPUL3FEATURES_FILECODE)
+#define AP_LATE_TASK_ENABLE_CACHE (0x00010000ul | PROC_CPU_FEATURE_CPUL3FEATURES_FILECODE)
+
+/*----------------------------------------------------------------------------------------
+ * T Y P E D E F S A N D S T R U C T U R E S
+ *----------------------------------------------------------------------------------------
+ */
+#define L3_SCRUBBER_CONTEXT_ARRAY_SIZE 4
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * Family specific call to check if L3 Features are supported.
+ *
+ * @param[in] L3FeatureServices L3 Feature family services.
+ * @param[in] Socket Processor socket to check.
+ * @param[in] StdHeader Config Handle for library, services.
+ *
+ * @retval TRUE L3 dependent features are supported
+ * @retval FALSE L3 dependent features are not supported
+ *
+ */
+typedef BOOLEAN F_L3_FEATURE_IS_SUPPORTED (
+ IN L3_FEATURE_FAMILY_SERVICES *L3FeatureServices,
+ IN UINT32 Socket,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ );
+
+/// Reference to a Method.
+typedef F_L3_FEATURE_IS_SUPPORTED *PF_L3_FEATURE_IS_SUPPORTED;
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * Family specific hook before L3 features are initialized.
+ *
+ * @param[in] L3FeatureServices L3 Feature family services.
+ * @param[in] Socket Processor socket to check.
+ * @param[in] StdHeader Config Handle for library, services.
+ *
+ */
+typedef VOID F_L3_FEATURE_BEFORE_INIT (
+ IN L3_FEATURE_FAMILY_SERVICES *L3FeatureServices,
+ IN UINT32 Socket,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ );
+
+/// Reference to a Method.
+typedef F_L3_FEATURE_BEFORE_INIT *PF_L3_FEATURE_BEFORE_INIT;
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * Family specific call to disable cache.
+ *
+ * @param[in] L3FeatureServices L3 Feature family services.
+ * @param[in] HtAssistEnabled Indicates whether Ht Assist is enabled.
+ * @param[in] StdHeader Config Handle for library, services.
+ *
+ */
+typedef VOID F_L3_FEATURE_DISABLE_CACHE (
+ IN L3_FEATURE_FAMILY_SERVICES *L3FeatureServices,
+ IN BOOLEAN HtAssistEnabled,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ );
+
+/// Reference to a Method.
+typedef F_L3_FEATURE_DISABLE_CACHE *PF_L3_FEATURE_DISABLE_CACHE;
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * Family specific call to disable cache.
+ *
+ * @param[in] L3FeatureServices L3 Feature family services.
+ * @param[in] StdHeader Config Handle for library, services.
+ *
+ * @return Family specific error value.
+ *
+ */
+typedef VOID F_L3_FEATURE_ENABLE_CACHE (
+ IN L3_FEATURE_FAMILY_SERVICES *L3FeatureServices,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ );
+
+/// Reference to a Method.
+typedef F_L3_FEATURE_ENABLE_CACHE *PF_L3_FEATURE_ENABLE_CACHE;
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * Family specific call to Initialize L3 Features
+ *
+ * @param[in] L3FeatureServices L3 Feature family services.
+ * @param[in] Socket Processor socket to enable.
+ * @param[in] StdHeader Config Handle for library, services.
+ *
+ */
+typedef VOID F_L3_FEATURE_INIT (
+ IN L3_FEATURE_FAMILY_SERVICES *L3FeatureServices,
+ IN UINT32 Socket,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ );
+
+/// Reference to a Method.
+typedef F_L3_FEATURE_INIT *PF_L3_FEATURE_INIT;
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * Family specific hook after L3 Features are initialized.
+ *
+ * @param[in] L3FeatureServices L3 Features family services.
+ * @param[in] Socket Processor socket to check.
+ * @param[in] StdHeader Config Handle for library, services.
+ *
+ */
+typedef VOID F_L3_FEATURE_AFTER_INIT (
+ IN L3_FEATURE_FAMILY_SERVICES *L3FeatureServices,
+ IN UINT32 Socket,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ );
+
+/// Reference to a Method.
+typedef F_L3_FEATURE_AFTER_INIT *PF_L3_FEATURE_AFTER_INIT;
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * Family specific call to save the L3 scrubber.
+ *
+ * @param[in] L3FeatureServices L3 Feature family services.
+ * @param[in] Socket Processor socket to check.
+ * @param[in] ScrubSettings Location to store current L3 scrubber settings.
+ * @param[in] StdHeader Config Handle for library, services.
+ *
+ */
+typedef VOID F_L3_FEATURE_GET_L3_SCRUB_CTRL (
+ IN L3_FEATURE_FAMILY_SERVICES *L3FeatureServices,
+ IN UINT32 Socket,
+ IN UINT32 ScrubSettings[L3_SCRUBBER_CONTEXT_ARRAY_SIZE],
+ IN AMD_CONFIG_PARAMS *StdHeader
+ );
+
+/// Reference to a Method.
+typedef F_L3_FEATURE_GET_L3_SCRUB_CTRL *PF_L3_FEATURE_GET_L3_SCRUB_CTRL;
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * Family specific call to restore the L3 scrubber.
+ *
+ * @param[in] L3FeatureServices L3 Feature family services.
+ * @param[in] Socket Processor socket to check.
+ * @param[in] ScrubSettings Contains L3 scrubber settings to restore.
+ * @param[in] StdHeader Config Handle for library, services.
+ *
+ */
+typedef VOID F_L3_FEATURE_SET_L3_SCRUB_CTRL (
+ IN L3_FEATURE_FAMILY_SERVICES *L3FeatureServices,
+ IN UINT32 Socket,
+ IN UINT32 ScrubSettings[L3_SCRUBBER_CONTEXT_ARRAY_SIZE],
+ IN AMD_CONFIG_PARAMS *StdHeader
+ );
+
+/// Reference to a Method.
+typedef F_L3_FEATURE_SET_L3_SCRUB_CTRL *PF_L3_FEATURE_SET_L3_SCRUB_CTRL;
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * Family specific call to check if HT Assist is supported.
+ *
+ * @param[in] L3FeatureServices L3 Feature family services.
+ * @param[in] PlatformConfig Contains the runtime modifiable feature input data
+ * @param[in] StdHeader Config Handle for library, services.
+ *
+ * @retval TRUE HT Assist is supported.
+ * @retval FALSE HT Assist is not supported.
+ *
+ */
+typedef BOOLEAN F_HT_ASSIST_IS_SUPPORTED (
+ IN L3_FEATURE_FAMILY_SERVICES *L3FeatureServices,
+ IN PLATFORM_CONFIGURATION *PlatformConfig,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ );
+
+/// Reference to a Method.
+typedef F_HT_ASSIST_IS_SUPPORTED *PF_HT_ASSIST_IS_SUPPORTED;
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * Family specific call to Initialize HT Assist
+ *
+ * @param[in] L3FeatureServices L3 Features family services.
+ * @param[in] Socket Processor socket to enable.
+ * @param[in] StdHeader Config Handle for library, services.
+ *
+ */
+typedef VOID F_HT_ASSIST_INIT (
+ IN L3_FEATURE_FAMILY_SERVICES *L3FeatureServices,
+ IN UINT32 Socket,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ );
+
+/// Reference to a Method.
+typedef F_HT_ASSIST_INIT *PF_HT_ASSIST_INIT;
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * Family specific call to provide non_optimal HT Assist support
+ *
+ * @param[in] L3FeatureServices L3 Feature family services.
+ * @param[in] Socket Processor socket to check.
+ * @param[in] StdHeader Config Handle for library, services.
+ *
+ * @return TRUE The system may be running with non-optimal settings.
+ * @return FALSE The system may is running optimally.
+ *
+ */
+typedef BOOLEAN F_HT_ASSIST_IS_NONOPTIMAL (
+ IN L3_FEATURE_FAMILY_SERVICES *L3FeatureServices,
+ IN UINT32 Socket,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ );
+
+/// Reference to a Method.
+typedef F_HT_ASSIST_IS_NONOPTIMAL *PF_HT_ASSIST_IS_NONOPTIMAL;
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * Family specific call to check if ATM Mode is supported.
+ *
+ * @param[in] L3FeatureServices L3 Features family services.
+ * @param[in] PlatformConfig Contains the runtime modifiable feature input data.
+ * @param[in] StdHeader Config Handle for library, services.
+ *
+ * @retval TRUE ATM Mode is supported.
+ * @retval FALSE ATM Mode is not supported.
+ *
+ */
+typedef BOOLEAN F_ATM_MODE_IS_SUPPORTED (
+ IN L3_FEATURE_FAMILY_SERVICES *L3FeatureServices,
+ IN PLATFORM_CONFIGURATION *PlatformConfig,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ );
+
+/// Reference to a Method.
+typedef F_ATM_MODE_IS_SUPPORTED *PF_ATM_MODE_IS_SUPPORTED;
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * Family specific call to Initialize ATM mode
+ *
+ * @param[in] L3FeatureServices L3 Features family services.
+ * @param[in] Socket Processor socket to enable.
+ * @param[in] StdHeader Config Handle for library, services.
+ *
+ */
+typedef VOID F_ATM_MODE_INIT (
+ IN L3_FEATURE_FAMILY_SERVICES *L3FeatureServices,
+ IN UINT32 Socket,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ );
+
+/// Reference to a Method.
+typedef F_ATM_MODE_INIT *PF_ATM_MODE_INIT;
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * Family specific call to check if Neighbor Cache Mode is supported.
+ *
+ * @param[in] L3FeatureServices L3 Features family services.
+ * @param[in] PlatformConfig Contains the runtime modifiable feature input data.
+ * @param[in] StdHeader Config Handle for library, services.
+ *
+ * @retval TRUE Neighbor Cache is supported.
+ * @retval FALSE Neighbor Cache is not supported.
+ *
+ */
+typedef BOOLEAN F_NBR_CACHE_IS_SUPPORTED (
+ IN L3_FEATURE_FAMILY_SERVICES *L3FeatureServices,
+ IN PLATFORM_CONFIGURATION *PlatformConfig,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ );
+
+/// Reference to a Method.
+typedef F_NBR_CACHE_IS_SUPPORTED *PF_NBR_CACHE_IS_SUPPORTED;
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * Family specific call to Initialize Neighbor Cache
+ *
+ * @param[in] L3FeatureServices L3 Features family services.
+ * @param[in] Socket Processor socket to enable.
+ * @param[in] StdHeader Config Handle for library, services.
+ *
+ */
+typedef VOID F_NBR_CACHE_INIT (
+ IN L3_FEATURE_FAMILY_SERVICES *L3FeatureServices,
+ IN UINT32 Socket,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ );
+
+/// Reference to a Method.
+typedef F_NBR_CACHE_INIT *PF_NBR_CACHE_INIT;
+
+/**
+ * Provide the interface to the L3 dependent features Family Specific Services.
+ *
+ * Use the methods or data in this struct to adapt the feature code to a specific cpu family or model (or stepping!).
+ * Each supported Family must provide an implementation for all methods in this interface, even if the
+ * implementation is a CommonReturn().
+ */
+struct _L3_FEATURE_FAMILY_SERVICES {
+ UINT16 Revision; ///< Interface version
+ // Public Methods.
+ PF_L3_FEATURE_IS_SUPPORTED IsL3FeatureSupported; ///< Method: Check if L3 dependent features are supported.
+ PF_L3_FEATURE_GET_L3_SCRUB_CTRL GetL3ScrubCtrl; ///< Method: Save/disable the L3 scrubber.
+ PF_L3_FEATURE_SET_L3_SCRUB_CTRL SetL3ScrubCtrl; ///< Method: Restore the L3 scrubber.
+ PF_L3_FEATURE_BEFORE_INIT HookBeforeInit; ///< Method: Hook before enabling L3 dependent features.
+ PF_L3_FEATURE_AFTER_INIT HookAfterInit; ///< Method: Hook after enabling L3 dependent features.
+ PF_L3_FEATURE_DISABLE_CACHE HookDisableCache; ///< Method: Core hook just before disabling cache.
+ PF_L3_FEATURE_ENABLE_CACHE HookEnableCache; ///< Method: Core hook just after enabling cache.
+ PF_HT_ASSIST_IS_SUPPORTED IsHtAssistSupported; ///< Method: Check if HT Assist is supported.
+ PF_HT_ASSIST_INIT HtAssistInit; ///< Method: Enable HT Assist.
+ PF_HT_ASSIST_IS_NONOPTIMAL IsNonOptimalConfig; ///< Method: Check if HT Assist is running optimally.
+ PF_ATM_MODE_IS_SUPPORTED IsAtmModeSupported; ///< Method: Check if ATM Mode is supported.
+ PF_ATM_MODE_INIT AtmModeInit; ///< Method: Enable ATM Mode.
+ PF_NBR_CACHE_IS_SUPPORTED IsNbrCacheSupported; ///< Method: Check if Neighbor Cache is supported.
+ PF_NBR_CACHE_INIT NbrCacheInit; ///< Method: Enable Neighbor Cache.
+};
+
+
+/*----------------------------------------------------------------------------------------
+ * F U N C T I O N S P R O T O T Y P E
+ *----------------------------------------------------------------------------------------
+ */
+AGESA_STATUS
+DisableAllCaches (
+ IN AP_EXE_PARAMS *ApExeParams
+ );
+
+AGESA_STATUS
+EnableAllCaches (
+ IN AP_EXE_PARAMS *ApExeParams
+ );
+
+#endif // _CPU_L3_FEATURES_H_
diff --git a/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuMsgBasedC1e.h b/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuMsgBasedC1e.h
new file mode 100644
index 0000000000..0fc252f109
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuMsgBasedC1e.h
@@ -0,0 +1,127 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * AMD AGESA CPU Message-based C1e Functions declarations.
+ *
+ * Contains code that declares the AGESA CPU C1e related APIs
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: CPU/Feature
+ * @e \$Revision: 84150 $ @e \$Date: 2012-12-12 15:46:25 -0600 (Wed, 12 Dec 2012) $
+ *
+ */
+/*
+ ******************************************************************************
+ *
+ * Copyright (c) 2008 - 2013, Advanced Micro Devices, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Advanced Micro Devices, Inc. nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ ******************************************************************************
+ */
+
+#ifndef _CPU_MSG_BASED_C1E_H_
+#define _CPU_MSG_BASED_C1E_H_
+
+/*----------------------------------------------------------------------------------------
+ * M I X E D (Definitions And Macros / Typedefs, Structures, Enums)
+ *----------------------------------------------------------------------------------------
+ */
+// Forward declaration needed for multi-structure mutual references
+AGESA_FORWARD_DECLARATION (MSG_BASED_C1E_FAMILY_SERVICES);
+
+/*----------------------------------------------------------------------------------------
+ * D E F I N I T I O N S A N D M A C R O S
+ *----------------------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------------------
+ * T Y P E D E F S A N D S T R U C T U R E S
+ *----------------------------------------------------------------------------------------
+ */
+/*---------------------------------------------------------------------------------------*/
+/**
+ * Family specific call to check if message-based C1e is supported.
+ *
+ * @param[in] MsgBasedC1eServices Contains the runtime modifiable feature input data.
+ * @param[in] Socket Processor socket to check.
+ * @param[in] StdHeader Config Handle for library, services.
+ *
+ * @retval TRUE Message-based C1e is supported.
+ * @retval FALSE Message-based C1e is not supported.
+ *
+ */
+typedef BOOLEAN F_MSG_BASED_C1E_IS_SUPPORTED (
+ IN MSG_BASED_C1E_FAMILY_SERVICES *MsgBasedC1eServices,
+ IN UINT32 Socket,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ );
+
+/// Reference to a Method.
+typedef F_MSG_BASED_C1E_IS_SUPPORTED *PF_MSG_BASED_C1E_IS_SUPPORTED;
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * Family specific call to enable hardware C1e.
+ *
+ * @param[in] MsgBasedC1eServices Hardware C1e services.
+ * @param[in] EntryPoint Timepoint designator.
+ * @param[in] PlatformConfig Contains the runtime modifiable feature input data.
+ * @param[in] StdHeader Config Handle for library, services.
+ *
+ * @return Family specific error value.
+ *
+ */
+typedef AGESA_STATUS F_MSG_BASED_C1E_INIT (
+ IN MSG_BASED_C1E_FAMILY_SERVICES *MsgBasedC1eServices,
+ IN UINT64 EntryPoint,
+ IN PLATFORM_CONFIGURATION *PlatformConfig,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ );
+
+/// Reference to a Method.
+typedef F_MSG_BASED_C1E_INIT *PF_MSG_BASED_C1E_INIT;
+
+/**
+ * Provide the interface to the hardware C1e Family Specific Services.
+ *
+ * Use the methods or data in this struct to adapt the feature code to a specific cpu family or model (or stepping!).
+ * Each supported Family must provide an implementation for all methods in this interface, even if the
+ * implementation is a CommonReturn().
+ */
+struct _MSG_BASED_C1E_FAMILY_SERVICES {
+ UINT16 Revision; ///< Interface version
+ // Public Methods.
+ PF_MSG_BASED_C1E_IS_SUPPORTED IsMsgBasedC1eSupported; ///< Method: Family specific call to check if hardware C1e is supported.
+ PF_MSG_BASED_C1E_INIT InitializeMsgBasedC1e; ///< Method: Family specific call to enable hardware C1e.
+};
+
+
+/*----------------------------------------------------------------------------------------
+ * F U N C T I O N S P R O T O T Y P E
+ *----------------------------------------------------------------------------------------
+ */
+
+#endif // _CPU_MSG_BASED_C1E_H_
diff --git a/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuPrefetchMode.h b/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuPrefetchMode.h
new file mode 100644
index 0000000000..1d837f5c24
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuPrefetchMode.h
@@ -0,0 +1,110 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * AMD AGESA CPU Prefetch Mode Functions declarations.
+ *
+ * Contains code that declares the AGESA CPU prefetch mode related APIs
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: CPU/Feature
+ * @e \$Revision: 84150 $ @e \$Date: 2012-12-12 15:46:25 -0600 (Wed, 12 Dec 2012) $
+ *
+ */
+/*
+ ******************************************************************************
+ *
+ * Copyright (c) 2008 - 2013, Advanced Micro Devices, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Advanced Micro Devices, Inc. nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ ******************************************************************************
+ */
+
+#ifndef _CPU_PREFETCH_MODE_H_
+#define _CPU_PREFETCH_MODE_H_
+
+/*----------------------------------------------------------------------------------------
+ * M I X E D (Definitions And Macros / Typedefs, Structures, Enums)
+ *----------------------------------------------------------------------------------------
+ */
+// Forward declaration needed for multi-structure mutual references
+AGESA_FORWARD_DECLARATION (PREFETCH_MODE_FAMILY_SERVICES);
+
+/*----------------------------------------------------------------------------------------
+ * D E F I N I T I O N S A N D M A C R O S
+ *----------------------------------------------------------------------------------------
+ */
+#define AP_LATE_TASK_CPU_PREFETCH_MODE (PROC_CPU_FEATURE_CPUPREFETCHMODE_FILECODE)
+
+/*----------------------------------------------------------------------------------------
+ * T Y P E D E F S A N D S T R U C T U R E S
+ *----------------------------------------------------------------------------------------
+ */
+
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * Family specific call to enable prefetch mode.
+ *
+ * @param[in] PrefetchModeServices Prefetch mode services.
+ * @param[in] PlatformConfig Contains the runtime modifiable feature input data.
+ * @param[in] StdHeader Config Handle for library, services.
+ *
+ * @return Family specific error value.
+ *
+ */
+typedef AGESA_STATUS F_PREFETCH_MODE_INIT (
+ IN PREFETCH_MODE_FAMILY_SERVICES *PrefetchModeServices,
+ IN PLATFORM_CONFIGURATION *PlatformConfig,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ );
+
+/// Reference to a Method.
+typedef F_PREFETCH_MODE_INIT *PF_PREFETCH_MODE_INIT;
+
+/**
+ * Provide the interface to the prefetch mode Family Specific Services.
+ *
+ * Use the methods or data in this struct to adapt the feature code to a specific cpu family or model (or stepping!).
+ * Each supported Family must provide an implementation for all methods in this interface, even if the
+ * implementation is a CommonReturn().
+ */
+struct _PREFETCH_MODE_FAMILY_SERVICES {
+ UINT16 Revision; ///< Interface version
+ // Public Methods.
+ PF_PREFETCH_MODE_INIT PrefetchModeControlOnCore; ///< Method: Family specific call to control prefetch mode.
+};
+
+
+/*----------------------------------------------------------------------------------------
+ * F U N C T I O N S P R O T O T Y P E
+ *----------------------------------------------------------------------------------------
+ */
+AGESA_STATUS
+CpuPrefetchModeApTask (
+ IN AP_EXE_PARAMS *ApExeParams
+ );
+
+#endif // _CPU_PREFETCH_MODE_H_
diff --git a/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuPsi.c b/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuPsi.c
new file mode 100644
index 0000000000..897723624c
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuPsi.c
@@ -0,0 +1,213 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * AMD AGESA CPU Power Status Indicator (PSI) feature support code.
+ *
+ * Contains code that declares the AGESA CPU PSI related APIs
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: CPU/Feature
+ * @e \$Revision: 84150 $ @e \$Date: 2012-12-12 15:46:25 -0600 (Wed, 12 Dec 2012) $
+ *
+ */
+/*
+ ******************************************************************************
+ *
+ * Copyright (c) 2008 - 2013, Advanced Micro Devices, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Advanced Micro Devices, Inc. nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ ******************************************************************************
+ */
+
+/*----------------------------------------------------------------------------------------
+ * M O D U L E S U S E D
+ *----------------------------------------------------------------------------------------
+ */
+#include "AGESA.h"
+#include "GeneralServices.h"
+#include "cpuFamilyTranslation.h"
+#include "cpuApicUtilities.h"
+#include "cpuFeatures.h"
+#include "cpuPsi.h"
+#include "OptionMultiSocket.h"
+#include "Filecode.h"
+CODE_GROUP (G1_PEICC)
+RDATA_GROUP (G1_PEICC)
+
+#define FILECODE PROC_CPU_FEATURE_CPUPSI_FILECODE
+
+/*----------------------------------------------------------------------------------------
+ * D E F I N I T I O N S A N D M A C R O S
+ *----------------------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------------------
+ * T Y P E D E F S A N D S T R U C T U R E S
+ *----------------------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------------------
+ * P R O T O T Y P E S O F L O C A L F U N C T I O N S
+ *----------------------------------------------------------------------------------------
+ */
+UINT32
+STATIC
+EnablePsiOnSocket (
+ IN VOID *EntryPoint,
+ IN AMD_CONFIG_PARAMS *StdHeader,
+ IN AMD_CPU_EARLY_PARAMS *CpuEarlyParams
+ );
+
+/*----------------------------------------------------------------------------------------
+ * E X P O R T E D F U N C T I O N S
+ *----------------------------------------------------------------------------------------
+ */
+extern CPU_FAMILY_SUPPORT_TABLE PsiFamilyServiceTable;
+extern OPTION_MULTISOCKET_CONFIGURATION OptionMultiSocketConfiguration;
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * Should Power Status Indicator (PSI) be enabled
+ *
+ * @param[in] PlatformConfig Contains the runtime modifiable feature input data.
+ * @param[in] StdHeader Config Handle for library, services.
+ *
+ * @retval TRUE PSI is supported.
+ * @retval FALSE PSI cannot be enabled.
+ *
+ */
+BOOLEAN
+STATIC
+IsPsiFeatureEnabled (
+ IN PLATFORM_CONFIGURATION *PlatformConfig,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ UINT32 Socket;
+ BOOLEAN IsEnabled;
+ PSI_FAMILY_SERVICES *PsiFamilyServices;
+ UINT32 VrmType;
+
+ IsEnabled = FALSE;
+
+ for (VrmType = 0; VrmType < MaxVrmType; VrmType++) {
+ if (PlatformConfig->VrmProperties[VrmType].LowPowerThreshold != 0) {
+ IsEnabled = TRUE;
+ break;
+ }
+ }
+
+ if (!IsEnabled) {
+ return FALSE;
+ }
+
+ for (Socket = 0; Socket < GetPlatformNumberOfSockets (); Socket++) {
+ if (IsProcessorPresent (Socket, StdHeader)) {
+ GetFeatureServicesOfSocket (&PsiFamilyServiceTable, Socket, (CONST VOID **)&PsiFamilyServices, StdHeader);
+ if ((PsiFamilyServices == NULL) || (!PsiFamilyServices->IsPsiSupported (PsiFamilyServices, Socket, PlatformConfig, StdHeader))) {
+ IsEnabled = FALSE;
+ break;
+ }
+ }
+ }
+ return IsEnabled;
+}
+
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * Enable Power Status Indicator (PSI)
+ *
+ * @param[in] EntryPoint Timepoint designator.
+ * @param[in] PlatformConfig Contains the runtime modifiable feature input data.
+ * @param[in] StdHeader Config Handle for library, services.
+ *
+ * @retval AGESA_SUCCESS Always succeeds.
+ *
+ */
+AGESA_STATUS
+STATIC
+InitializePsiFeature (
+ IN UINT64 EntryPoint,
+ IN PLATFORM_CONFIGURATION *PlatformConfig,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ AP_TASK TaskPtr;
+ AGESA_STATUS AgesaStatus;
+ AMD_CPU_EARLY_PARAMS CpuEarlyParams;
+
+ IDS_HDT_CONSOLE (CPU_TRACE, " PSI mode is being initialized\n");
+
+ CpuEarlyParams.PlatformConfig = *PlatformConfig;
+
+ TaskPtr.FuncAddress.PfApTaskIOC = EnablePsiOnSocket;
+ TaskPtr.DataTransfer.DataSizeInDwords = 2;
+ TaskPtr.DataTransfer.DataPtr = &EntryPoint;
+ TaskPtr.DataTransfer.DataTransferFlags = 0;
+ TaskPtr.ExeFlags = PASS_EARLY_PARAMS | TASK_HAS_OUTPUT;
+ AgesaStatus = OptionMultiSocketConfiguration.BscRunCodeOnAllSystemCore0s (&TaskPtr, StdHeader, &CpuEarlyParams);
+
+ IDS_HDT_CONSOLE (CPU_TRACE, " PSI mode is enabled\n");
+
+ return AgesaStatus;
+}
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * AP task to enable PSI
+ *
+ * @param[in] EntryPoint Timepoint designator.
+ * @param[in] StdHeader Config Handle for library, services.
+ * @param[in] CpuEarlyParams Service parameters.
+ *
+ */
+UINT32
+STATIC
+EnablePsiOnSocket (
+ IN VOID *EntryPoint,
+ IN AMD_CONFIG_PARAMS *StdHeader,
+ IN AMD_CPU_EARLY_PARAMS *CpuEarlyParams
+ )
+{
+ AGESA_STATUS CalledStatus;
+ PSI_FAMILY_SERVICES *PsiFamilyServices;
+
+ CalledStatus = AGESA_UNSUPPORTED;
+ GetFeatureServicesOfCurrentCore (&PsiFamilyServiceTable, (CONST VOID **)&PsiFamilyServices, StdHeader);
+ if (PsiFamilyServices != NULL) {
+ CalledStatus = PsiFamilyServices->EnablePsiOnSocket (PsiFamilyServices, *((UINT64 *) EntryPoint), &CpuEarlyParams->PlatformConfig, StdHeader);
+ }
+ return (UINT32) CalledStatus;
+}
+
+CONST CPU_FEATURE_DESCRIPTOR ROMDATA CpuFeaturePsi =
+{
+ CpuPsi,
+ (CPU_FEAT_AFTER_POST_MTRR_SYNC | CPU_FEAT_AFTER_RESUME_MTRR_SYNC),
+ IsPsiFeatureEnabled,
+ InitializePsiFeature
+};
diff --git a/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuPsi.h b/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuPsi.h
new file mode 100644
index 0000000000..ad2a5e545c
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuPsi.h
@@ -0,0 +1,130 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * AMD AGESA CPU Power Status Indicator (PSI) Functions declarations.
+ *
+ * Contains code that declares the AGESA CPU PSI related APIs
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: CPU/Feature
+ * @e \$Revision: 84150 $ @e \$Date: 2012-12-12 15:46:25 -0600 (Wed, 12 Dec 2012) $
+ *
+ */
+/*
+ ******************************************************************************
+ *
+ * Copyright (c) 2008 - 2013, Advanced Micro Devices, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Advanced Micro Devices, Inc. nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ ******************************************************************************
+ */
+
+#ifndef _CPU_PSI_H_
+#define _CPU_PSI_H_
+
+/*----------------------------------------------------------------------------------------
+ * M I X E D (Definitions And Macros / Typedefs, Structures, Enums)
+ *----------------------------------------------------------------------------------------
+ */
+// Forward declaration needed for multi-structure mutual references
+AGESA_FORWARD_DECLARATION (PSI_FAMILY_SERVICES);
+
+/*----------------------------------------------------------------------------------------
+ * D E F I N I T I O N S A N D M A C R O S
+ *----------------------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------------------
+ * T Y P E D E F S A N D S T R U C T U R E S
+ *----------------------------------------------------------------------------------------
+ */
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * Family specific call to check if Power Status Indicator (PSI) is supported.
+ *
+ * @param[in] PsiServices PSI services.
+ * @param[in] Socket Zero-based socket number.
+ * @param[in] PlatformConfig Contains the runtime modifiable feature input data.
+ * @param[in] StdHeader Config Handle for library, services.
+ *
+ * @retval TRUE PSI is supported.
+ * @retval FALSE PSI is not supported.
+ *
+ */
+typedef BOOLEAN F_PSI_IS_SUPPORTED (
+ IN PSI_FAMILY_SERVICES *PsiServices,
+ IN UINT32 Socket,
+ IN PLATFORM_CONFIGURATION *PlatformConfig,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ );
+
+/// Reference to a Method.
+typedef F_PSI_IS_SUPPORTED *PF_PSI_IS_SUPPORTED;
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * Family specific call to enable PSI.
+ *
+ * @param[in] PsiServices PSI services.
+ * @param[in] EntryPoint Timepoint designator.
+ * @param[in] PlatformConfig Contains the runtime modifiable feature input data.
+ * @param[in] StdHeader Config Handle for library, services.
+ *
+ * @return Family specific error value.
+ *
+ */
+typedef AGESA_STATUS F_PSI_INIT (
+ IN PSI_FAMILY_SERVICES *PsiServices,
+ IN UINT64 EntryPoint,
+ IN PLATFORM_CONFIGURATION *PlatformConfig,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ );
+
+/// Reference to a Method.
+typedef F_PSI_INIT *PF_PSI_INIT;
+
+/**
+ * Provide the interface to the PSI Family Specific Services.
+ *
+ * Use the methods or data in this struct to adapt the feature code to a specific cpu family or model (or stepping!).
+ * Each supported Family must provide an implementation for all methods in this interface, even if the
+ * implementation is a CommonReturn().
+ */
+typedef struct _PSI_FAMILY_SERVICES {
+ UINT16 Revision; ///< Interface version
+ // Public Methods.
+ PF_PSI_IS_SUPPORTED IsPsiSupported; ///< Method: Family specific call to check if PSI is supported.
+ PF_PSI_INIT EnablePsiOnSocket; ///< Method: Family specific call to enable PSI.
+} PSI_FAMILY_SERVICES;
+
+
+/*----------------------------------------------------------------------------------------
+ * F U N C T I O N S P R O T O T Y P E
+ *----------------------------------------------------------------------------------------
+ */
+
+#endif // _CPU_PSI_H_
diff --git a/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuPstateGather.c b/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuPstateGather.c
new file mode 100644
index 0000000000..796b455e25
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuPstateGather.c
@@ -0,0 +1,410 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * AMD CPU Pstate Data Gather Function.
+ *
+ * Contains code to collect all the Pstate related information from MSRs, and PCI registers.
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: CPU
+ * @e \$Revision: 84150 $ @e \$Date: 2012-12-12 15:46:25 -0600 (Wed, 12 Dec 2012) $
+ *
+ */
+/*****************************************************************************
+ *
+ * Copyright (c) 2008 - 2013, Advanced Micro Devices, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Advanced Micro Devices, Inc. nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ ******************************************************************************
+ */
+
+
+/*
+ *----------------------------------------------------------------------------
+ * MODULES USED
+ *
+ *----------------------------------------------------------------------------
+ */
+#include "AGESA.h"
+#include "amdlib.h"
+#include "OptionPstate.h"
+#include "cpuRegisters.h"
+#include "cpuServices.h"
+#include "GeneralServices.h"
+#include "cpuPostInit.h"
+#include "Ids.h"
+#include "cpuFamilyTranslation.h"
+#include "cpuPstateTables.h"
+#include "cpuApicUtilities.h"
+#include "cpuFeatures.h"
+#include "Filecode.h"
+CODE_GROUP (G1_PEICC)
+RDATA_GROUP (G1_PEICC)
+
+#define FILECODE PROC_CPU_FEATURE_CPUPSTATEGATHER_FILECODE
+
+/*----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *----------------------------------------------------------------------------
+ */
+extern OPTION_PSTATE_POST_CONFIGURATION OptionPstatePostConfiguration; // global user config record
+extern CPU_FAMILY_SUPPORT_TABLE PstateFamilyServiceTable;
+
+/*----------------------------------------------------------------------------
+ * TYPEDEFS AND STRUCTURES
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * PROTOTYPES OF LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+AGESA_STATUS
+PStateGatherStub (
+ IN AMD_CONFIG_PARAMS *StdHeader,
+ IN OUT S_CPU_AMD_PSTATE *PStateStrucPtr
+ );
+
+AGESA_STATUS
+PStateGatherMain (
+ IN AMD_CONFIG_PARAMS *StdHeader,
+ IN OUT S_CPU_AMD_PSTATE *PStateStrucPtr
+ );
+
+
+/*----------------------------------------------------------------------------
+ * EXPORTED FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+VOID
+PStateGather (
+ IN OUT VOID *PStateBuffer,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ );
+
+/**
+ *---------------------------------------------------------------------------------------
+ *
+ * PStateGatherData
+ *
+ * Description:
+ * This function will gather PState information from the MSRs and fill up the
+ * pStateBuf. This buffer will be used by the PState Leveling, and PState Table
+ * generation code later.
+ *
+ * Parameters:
+ * @param[in] *PlatformConfig
+ * @param[in, out] *PStateStrucPtr
+ * @param[in] *StdHeader
+ *
+ * @retval AGESA_STATUS
+ *
+ *---------------------------------------------------------------------------------------
+ **/
+AGESA_STATUS
+PStateGatherData (
+ IN PLATFORM_CONFIGURATION *PlatformConfig,
+ IN OUT S_CPU_AMD_PSTATE *PStateStrucPtr,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+
+
+ AGESA_STATUS AgesaStatus;
+
+ AGESA_TESTPOINT (TpProcCpuEntryPstateGather, StdHeader);
+ AgesaStatus = AGESA_SUCCESS;
+
+ // Gather data for ACPI Tables if ACPI P-States/C-States object generation is enabled.
+ if ((PlatformConfig->UserOptionPState) || (IsFeatureEnabled (IoCstate, PlatformConfig, StdHeader))) {
+ AgesaStatus = (*(OptionPstatePostConfiguration.PstateGather)) (StdHeader, PStateStrucPtr);
+ // Note: Split config struct into PEI/DXE halves. This one is PEI.
+ }
+
+ return AgesaStatus;
+}
+
+/**--------------------------------------------------------------------------------------
+ *
+ * PStateGatherStub
+ *
+ * Description:
+ * This is the default routine for use when the PState option is NOT requested.
+ * The option install process will create and fill the transfer vector with
+ * the address of the proper routine (Main or Stub). The link optimizer will
+ * strip out of the .DLL the routine that is not used.
+ *
+ * Parameters:
+ * @param[in] *StdHeader
+ * @param[in, out] *PStateStrucPtr
+ *
+ * @retval AGESA_STATUS
+ *
+ *---------------------------------------------------------------------------------------
+ **/
+AGESA_STATUS
+PStateGatherStub (
+ IN AMD_CONFIG_PARAMS *StdHeader,
+ IN OUT S_CPU_AMD_PSTATE *PStateStrucPtr
+ )
+{
+ return AGESA_UNSUPPORTED;
+}
+
+/**--------------------------------------------------------------------------------------
+ *
+ * PStateGatherMain
+ *
+ * Description:
+ * This is the common routine for BSP gathering the Pstate data.
+ *
+ * Parameters:
+ * @param[in] *StdHeader
+ * @param[in, out] *PStateStrucPtr
+ *
+ * @retval AGESA_STATUS
+ *
+ *---------------------------------------------------------------------------------------
+ **/
+AGESA_STATUS
+PStateGatherMain (
+ IN AMD_CONFIG_PARAMS *StdHeader,
+ IN OUT S_CPU_AMD_PSTATE *PStateStrucPtr
+ )
+{
+ AP_TASK TaskPtr;
+ UINT32 BscSocket;
+ UINT32 Ignored;
+ UINT32 PopulatedSockets;
+ UINT32 NumberOfSockets;
+ UINT32 Socket;
+ AGESA_STATUS IgnoredSts;
+ PSTATE_LEVELING *PStateBufferPtr;
+ PSTATE_CPU_FAMILY_SERVICES *FamilyServices;
+ UINT32 MaxState;
+ UINT8 IgnoredByte;
+
+ ASSERT (IsBsp (StdHeader, &IgnoredSts));
+
+ FamilyServices = NULL;
+ GetFeatureServicesOfCurrentCore (&PstateFamilyServiceTable, (CONST VOID **)&FamilyServices, StdHeader);
+ ASSERT (FamilyServices != NULL);
+
+ PopulatedSockets = 1;
+ PStateBufferPtr = PStateStrucPtr->PStateLevelingStruc;
+
+ NumberOfSockets = GetPlatformNumberOfSockets ();
+ IdentifyCore (StdHeader, &BscSocket, &Ignored, &Ignored, &IgnoredSts);
+
+ PStateStrucPtr->SizeOfBytes = sizeof (S_CPU_AMD_PSTATE);
+
+ MaxState = 0;
+ FamilyServices->GetPstateMaxState (FamilyServices, &MaxState, &IgnoredByte, StdHeader);
+
+ TaskPtr.FuncAddress.PfApTaskI = PStateGather;
+ //
+ // Calculate max buffer size in dwords that need to pass to ap task.
+ //
+ TaskPtr.DataTransfer.DataSizeInDwords = (UINT16) ((MaxState + 1) * (SIZE_IN_DWORDS (S_PSTATE_VALUES)));
+ TaskPtr.ExeFlags = WAIT_FOR_CORE;
+ TaskPtr.DataTransfer.DataPtr = PStateBufferPtr;
+ TaskPtr.DataTransfer.DataTransferFlags = DATA_IN_MEMORY;
+
+ //
+ //Get P-States and fill the PStateBufferPtr for BSP
+ //
+ ApUtilTaskOnExecutingCore (&TaskPtr, StdHeader, NULL);
+
+ //
+ //Calculate next node buffer address
+ //
+ PStateBufferPtr->SocketNumber = (UINT8) BscSocket;
+ PStateBufferPtr->PStateLevelingSizeOfBytes = (UINT16) (sizeof (PSTATE_LEVELING) + (UINT32) (PStateBufferPtr->PStateCoreStruct[0].PStateMaxValue * sizeof (S_PSTATE_VALUES)));
+ PStateStrucPtr->SizeOfBytes += (UINT32) (PStateBufferPtr->PStateCoreStruct[0].PStateMaxValue * sizeof (S_PSTATE_VALUES));
+ PStateBufferPtr = (PSTATE_LEVELING *) ((UINT8 *) PStateBufferPtr + (UINTN) sizeof (PSTATE_LEVELING) + (UINTN) (PStateBufferPtr->PStateCoreStruct[0].PStateMaxValue * sizeof (S_PSTATE_VALUES)));
+ CpuGetPStateLevelStructure (&PStateBufferPtr, PStateStrucPtr, 1, StdHeader);
+ //
+ //Get CPU P-States and fill the PStateBufferPtr for each node(BSC)
+ //
+ for (Socket = 0; Socket < NumberOfSockets; Socket++) {
+ if (Socket != BscSocket) {
+ if (IsProcessorPresent (Socket, StdHeader)) {
+ PopulatedSockets++;
+ LibAmdMemFill (PStateBufferPtr, 0, sizeof (PSTATE_LEVELING), StdHeader);
+ TaskPtr.DataTransfer.DataPtr = PStateBufferPtr;
+ ApUtilRunCodeOnSocketCore ((UINT8)Socket, 0, &TaskPtr, StdHeader);
+ PStateBufferPtr->SocketNumber = (UINT8) Socket;
+ //
+ //Calculate next node buffer address
+ //
+ PStateBufferPtr->PStateLevelingSizeOfBytes = (UINT16) (sizeof (PSTATE_LEVELING) + (UINT32) (PStateBufferPtr->PStateCoreStruct[0].PStateMaxValue * sizeof (S_PSTATE_VALUES)));
+ PStateStrucPtr->SizeOfBytes += PStateBufferPtr->PStateLevelingSizeOfBytes;
+ PStateBufferPtr = (PSTATE_LEVELING *) ((UINT8 *) PStateBufferPtr + (UINTN) sizeof (PSTATE_LEVELING) + (UINTN) (PStateBufferPtr->PStateCoreStruct[0].PStateMaxValue * sizeof (S_PSTATE_VALUES)));
+ }
+ }
+ }
+ PStateStrucPtr->TotalSocketInSystem = PopulatedSockets;
+
+ return AGESA_SUCCESS;
+}
+/**--------------------------------------------------------------------------------------
+ *
+ * PStateGather
+ *
+ * Description:
+ * This is the common routine run on each BSC for gathering Pstate data.
+ *
+ * Parameters:
+ * @param[in,out] *PStateBuffer
+ * @param[in] *StdHeader
+ *
+ * @retval VOID
+ *
+ *---------------------------------------------------------------------------------------
+ **/
+VOID
+PStateGather (
+ IN OUT VOID *PStateBuffer,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ UINT32 k;
+ UINT32 IddVal;
+ UINT32 IddDiv;
+ UINT32 NodeNum;
+ UINT32 CoreNum;
+ UINT32 TempVar_c;
+ UINT32 TotalEnabledPStates;
+ UINT32 SwPstate;
+ UINT8 BoostStates;
+ PCI_ADDR PciAddress;
+ PSTATE_LEVELING *PStateBufferPtr;
+ BOOLEAN PStateEnabled;
+ PSTATE_CPU_FAMILY_SERVICES *FamilyServices;
+ UINT32 Socket;
+ AGESA_STATUS IgnoredSts;
+ CPUID_DATA CpuId;
+
+ PStateBufferPtr = (PSTATE_LEVELING *) PStateBuffer;
+ TotalEnabledPStates = 0;
+ FamilyServices = NULL;
+ PStateEnabled = FALSE;
+
+ GetFeatureServicesOfCurrentCore (&PstateFamilyServiceTable, (CONST VOID **)&FamilyServices, StdHeader);
+ ASSERT (FamilyServices != NULL);
+
+ //
+ /// Sockets number: code looking at PStateBufferPtr->TotalCoresInNode
+ /// needs to know it is Processor (or socket) core count and NOT a Node Core count.
+ GetActiveCoresInCurrentSocket (&CoreNum, StdHeader);
+ PStateBufferPtr->TotalCoresInNode = (UINT8) CoreNum;
+
+ //
+ // Assume current CoreNum always zero.(BSC)
+ //
+ GetCurrentNodeAndCore (&NodeNum, &CoreNum, StdHeader);
+
+ PStateBufferPtr->CreateAcpiTables = 1;
+
+ //
+ // We need to know the max pstate state in this socket.
+ //
+ FamilyServices->GetPstateMaxState (FamilyServices, &TempVar_c, &BoostStates, StdHeader);
+ PStateBufferPtr->PStateCoreStruct[0].PStateMaxValue = (UINT8) TempVar_c;
+ PStateBufferPtr->PStateCoreStruct[0].NumberOfBoostedStates = BoostStates;
+
+ for (k = 0; k <= TempVar_c; k++) {
+ // Check if PState is enabled
+ FamilyServices->GetPstateRegisterInfo ( FamilyServices,
+ k,
+ &PStateEnabled,
+ &IddVal,
+ &IddDiv,
+ &SwPstate,
+ StdHeader);
+
+ LibAmdMemFill (&(PStateBufferPtr->PStateCoreStruct[0].PStateStruct[k]), 0, sizeof (S_PSTATE_VALUES), StdHeader);
+
+ if (PStateEnabled) {
+ FamilyServices->GetPstateFrequency (
+ FamilyServices,
+ (UINT8) k,
+ &(PStateBufferPtr->PStateCoreStruct[0].PStateStruct[k].CoreFreq),
+ StdHeader);
+
+ FamilyServices->GetPstatePower (
+ FamilyServices,
+ (UINT8) k,
+ &(PStateBufferPtr->PStateCoreStruct[0].PStateStruct[k].Power),
+ StdHeader);
+
+ PStateBufferPtr->PStateCoreStruct[0].PStateStruct[k].IddValue = IddVal;
+ PStateBufferPtr->PStateCoreStruct[0].PStateStruct[k].IddDiv = IddDiv;
+ PStateBufferPtr->PStateCoreStruct[0].PStateStruct[k].SwPstateNumber = SwPstate;
+
+ PStateBufferPtr->PStateCoreStruct[0].PStateStruct[k].PStateEnable = 1;
+ TotalEnabledPStates++;
+ }
+ } // for (k = 0; k < MPPSTATE_MAXIMUM_STATES; k++)
+
+ // Don't create ACPI Tables if there is one or less than one PState is enabled
+ if (TotalEnabledPStates <= 1) {
+ PStateBufferPtr[0].CreateAcpiTables = 0;
+ }
+
+ //--------------------Check Again--------------------------------
+
+ IdentifyCore (StdHeader, &Socket, &NodeNum, &CoreNum, &IgnoredSts);
+ // Get the PCI address of internal die 0 as it is the only die programmed.
+ GetPciAddress (StdHeader, Socket, 0, &PciAddress, &IgnoredSts);
+ PciAddress.Address.Function = FUNC_3;
+ PciAddress.Address.Register = NORTH_BRIDGE_CAPABILITIES_REG;
+ TempVar_c = 0;
+ LibAmdPciRead (AccessWidth32, PciAddress, &TempVar_c, StdHeader);
+ PStateBufferPtr->PStateCoreStruct[0].HtcCapable =
+ (UINT8) ((TempVar_c & 0x00000400) >> 10); // Bit 10
+
+ TempVar_c = 0;
+ PciAddress.Address.Register = HARDWARE_THERMAL_CTRL_REG;
+ LibAmdPciRead (AccessWidth32, PciAddress, &TempVar_c, StdHeader);
+ PStateBufferPtr->PStateCoreStruct[0].HtcPstateLimit =
+ (UINT8) ((TempVar_c & 0x70000000) >> 28); // Bits 30:28
+
+ // Get LocalApicId from CPUID Fn0000_0001_EBX
+ LibAmdCpuidRead (AMD_CPUID_APICID_LPC_BID, &CpuId, StdHeader);
+ PStateBufferPtr->PStateCoreStruct[0].LocalApicId = (UINT8) ((CpuId.EBX_Reg & 0xFF000000) >> 24);
+}
+
+
+/*----------------------------------------------------------------------------
+ * LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
diff --git a/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuPstateHpcMode.h b/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuPstateHpcMode.h
new file mode 100644
index 0000000000..f8f41bfeb6
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuPstateHpcMode.h
@@ -0,0 +1,98 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * AMD AGESA CPU Pstate HPC mode Functions declarations.
+ *
+ * Contains code that declares the AGESA CPU Pstate HPC mode related APIs
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: CPU/Feature
+ * @e \$Revision: 84150 $ @e \$Date: 2012-12-12 15:46:25 -0600 (Wed, 12 Dec 2012) $
+ *
+ */
+/*
+ ******************************************************************************
+ *
+ * Copyright (c) 2008 - 2013, Advanced Micro Devices, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Advanced Micro Devices, Inc. nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ ******************************************************************************
+ */
+
+#ifndef _CPU_PSTATE_HPC_MODE_H_
+#define _CPU_PSTATE_HPC_MODE_H_
+
+/*----------------------------------------------------------------------------------------
+ * M I X E D (Definitions And Macros / Typedefs, Structures, Enums)
+ *----------------------------------------------------------------------------------------
+ */
+AGESA_FORWARD_DECLARATION (PSTATE_HPC_MODE_FAMILY_SERVICES);
+
+/*----------------------------------------------------------------------------------------
+ * D E F I N I T I O N S A N D M A C R O S
+ *----------------------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------------------
+ * T Y P E D E F S A N D S T R U C T U R E S
+ *----------------------------------------------------------------------------------------
+ */
+/*---------------------------------------------------------------------------------------*/
+/**
+ * Family specific call to enable P-state HPC mode
+ *
+ * @param[in] PstateHpcModeService P-state HPC mode services.
+ * @param[in] StdHeader Config Handle for library, services.
+ *
+ * @return Family specific error value.
+ *
+ */
+typedef AGESA_STATUS F_PSTATE_HPC_MODE_INIT (
+ IN PSTATE_HPC_MODE_FAMILY_SERVICES *PstateHpcModeService,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ );
+
+/// Reference to a Method.
+typedef F_PSTATE_HPC_MODE_INIT *PF_PSTATE_HPC_MODE_INIT;
+
+/**
+ * Provide the interface to the P-state HPC mode Family Specific Services.
+ *
+ * Use the methods or data in this struct to adapt the feature code to a specific cpu family or model (or stepping!).
+ * Each supported Family must provide an implementation for all methods in this interface, even if the
+ * implementation is a CommonReturn().
+ */
+struct _PSTATE_HPC_MODE_FAMILY_SERVICES {
+ UINT16 Revision; ///< Interface version
+ // Public Methods.
+ PF_PSTATE_HPC_MODE_INIT EnablePstateHpcMode; ///< Method: Family specific call to enable P-state HPC mode.
+};
+/*----------------------------------------------------------------------------------------
+ * F U N C T I O N S P R O T O T Y P E
+ *----------------------------------------------------------------------------------------
+ */
+
+#endif // _CPU_PSTATE_HPC_MODE_H_
diff --git a/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuPstateLeveling.c b/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuPstateLeveling.c
new file mode 100644
index 0000000000..ab135b9ec6
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuPstateLeveling.c
@@ -0,0 +1,1100 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * AMD CPU Pstate Leveling Function.
+ *
+ * Contains code to level the Pstates in a multi-socket system
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: CPU
+ * @e \$Revision: 84150 $ @e \$Date: 2012-12-12 15:46:25 -0600 (Wed, 12 Dec 2012) $
+ *
+ */
+/*****************************************************************************
+ *
+ * Copyright (c) 2008 - 2013, Advanced Micro Devices, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Advanced Micro Devices, Inc. nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ ******************************************************************************
+ *----------------------------------------------------------------------------
+ */
+
+
+/*
+ *----------------------------------------------------------------------------
+ * MODULES USED
+ *
+ *----------------------------------------------------------------------------
+ */
+#include "AGESA.h"
+#include "amdlib.h"
+#include "OptionPstate.h"
+#include "cpuLateInit.h"
+#include "cpuRegisters.h"
+#include "cpuPostInit.h"
+#include "Ids.h"
+#include "cpuFamilyTranslation.h"
+#include "cpuPstateTables.h"
+#include "cpuApicUtilities.h"
+#include "cpuServices.h"
+#include "GeneralServices.h"
+#include "Filecode.h"
+CODE_GROUP (G1_PEICC)
+RDATA_GROUP (G1_PEICC)
+
+#define FILECODE PROC_CPU_FEATURE_CPUPSTATELEVELING_FILECODE
+
+/*----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *----------------------------------------------------------------------------
+ */
+extern OPTION_PSTATE_POST_CONFIGURATION OptionPstatePostConfiguration; // global user config record
+extern CPU_FAMILY_SUPPORT_TABLE PstateFamilyServiceTable;
+
+/*----------------------------------------------------------------------------
+ * TYPEDEFS AND STRUCTURES
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * PROTOTYPES OF LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+AGESA_STATUS
+PutAllCoreInPState0 (
+ IN OUT PSTATE_LEVELING *PStateBufferPtr,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ );
+
+AGESA_STATUS
+StartPstateMsrModify (
+ IN S_CPU_AMD_PSTATE *CpuAmdPState,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ );
+
+VOID
+STATIC
+PutCoreInPState0 (
+ IN VOID *PStateBuffer,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ );
+
+AGESA_STATUS
+PStateLevelingStub (
+ IN OUT S_CPU_AMD_PSTATE *PStateStrucPtr,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ );
+
+AGESA_STATUS
+PStateLevelingMain (
+ IN OUT S_CPU_AMD_PSTATE *PStateStrucPtr,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ );
+
+VOID
+CorePstateRegModify (
+ IN VOID *CpuAmdPState,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ );
+
+/**
+ *---------------------------------------------------------------------------------------
+ *
+ * PStateLeveling
+ *
+ * Description:
+ * This function will populate the PStateBuffer, after doing the PState Leveling
+ * Note: This function should be called for every core in the system.
+ *
+ * Parameters:
+ * @param[in,out] *PStateStrucPtr
+ * @param[in] *StdHeader
+ *
+ * @retval AGESA_STATUS
+ *
+ *---------------------------------------------------------------------------------------
+ **/
+AGESA_STATUS
+PStateLeveling (
+ IN OUT S_CPU_AMD_PSTATE *PStateStrucPtr,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ AGESA_TESTPOINT (TpProcCpuEntryPstateLeveling, StdHeader);
+ return ((*(OptionPstatePostConfiguration.PstateLeveling)) (PStateStrucPtr, StdHeader));
+ // Note: Split config struct into PEI/DXE halves. This one is PEI.
+}
+
+/**--------------------------------------------------------------------------------------
+ *
+ * PStateLevelingStub
+ *
+ * Description:
+ * This is the default routine for use when the PState option is NOT requested.
+ * The option install process will create and fill the transfer vector with
+ * the address of the proper routine (Main or Stub). The link optimizer will
+ * strip out of the .DLL the routine that is not used.
+ *
+ * Parameters:
+ * @param[in,out] *PStateStrucPtr
+ * @param[in] *StdHeader
+ *
+ * @retval AGESA_STATUS
+ *
+ *---------------------------------------------------------------------------------------
+ **/
+AGESA_STATUS
+PStateLevelingStub (
+ IN OUT S_CPU_AMD_PSTATE *PStateStrucPtr,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ return AGESA_UNSUPPORTED;
+}
+
+/**--------------------------------------------------------------------------------------
+ *
+ * PStateLevelingMain
+ *
+ * Description:
+ * This is the common routine for creating the ACPI information tables.
+ *
+ * Parameters:
+ * @param[in,out] *PStateStrucPtr
+ * @param[in] *StdHeader
+ *
+ * @retval AGESA_STATUS
+ *
+ *---------------------------------------------------------------------------------------
+ **/
+AGESA_STATUS
+PStateLevelingMain (
+ IN OUT S_CPU_AMD_PSTATE *PStateStrucPtr,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ UINT32 i;
+ UINT32 k;
+ UINT32 m;
+ UINT32 TotalIterations;
+ UINT32 LogicalSocketCount;
+ UINT32 TempVar_a;
+ UINT32 TempVar_b;
+ UINT32 TempVar_c;
+ UINT32 TempVar_d;
+ UINT32 TempVar_e;
+ UINT32 TempVar_f;
+ PCI_ADDR PciAddress;
+
+ UINT32 TempFreqArray[20];
+ UINT32 TempPowerArray[20];
+ UINT32 TempIddValueArray[20];
+ UINT32 TempIddDivArray[20];
+ UINT32 TempSocketPiArray[20];
+ UINT32 TempSwP0Array[MAX_SOCKETS_SUPPORTED];
+
+ BOOLEAN TempFlag1;
+ BOOLEAN TempFlag2;
+ BOOLEAN TempFlag3;
+ BOOLEAN TempFlag4;
+ BOOLEAN AllCoresHaveHtcCapEquToZeroFlag;
+ BOOLEAN AllCoreHaveMaxOnePStateFlag;
+ BOOLEAN PstateMaxValEquToPstateHtcLimitFlag;
+ BOOLEAN AtLeastOneCoreHasPstateHtcLimitEquToOneFlag;
+ BOOLEAN PstateMaxValMinusHtcPstateLimitLessThan2Flag;
+ PSTATE_LEVELING *PStateBufferPtr;
+ PSTATE_LEVELING *PStateBufferPtrTmp;
+ UINT32 MaxPstateInNode;
+ AGESA_STATUS Status;
+
+ TempFlag1 = FALSE;
+ TempFlag2 = FALSE;
+ TempFlag3 = FALSE;
+ TempFlag4 = FALSE;
+ AllCoresHaveHtcCapEquToZeroFlag = FALSE;
+ AllCoreHaveMaxOnePStateFlag = FALSE;
+ PstateMaxValEquToPstateHtcLimitFlag = FALSE;
+ AtLeastOneCoreHasPstateHtcLimitEquToOneFlag = FALSE;
+ PstateMaxValMinusHtcPstateLimitLessThan2Flag = FALSE;
+ PStateBufferPtr = PStateStrucPtr->PStateLevelingStruc;
+ Status = AGESA_SUCCESS;
+
+ if (PStateBufferPtr[0].SetPState0 == PSTATE_FLAG_1) {
+ PStateBufferPtr[0].AllCpusHaveIdenticalPStates = TRUE;
+ PStateBufferPtr[0].InitStruct = 1;
+ return AGESA_UNSUPPORTED;
+ }
+
+ LogicalSocketCount = PStateStrucPtr->TotalSocketInSystem;
+ ASSERT (LogicalSocketCount <= MAX_SOCKETS_SUPPORTED);
+
+ // This section of code will execute only for "core 0" i.e. BSP
+ // Read P-States of all the cores.
+ if (PStateBufferPtr[0].InitStruct == 0) {
+ // Determine 'software' P0 indices for each socket
+ for (i = 0; i < LogicalSocketCount; i++) {
+ CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader);
+ TempSwP0Array[i] = (UINT32) (PStateBufferPtrTmp->PStateCoreStruct[0].NumberOfBoostedStates);
+ }
+
+ // Check if core frequency and power are same across all sockets.
+ TempFlag1 = FALSE;
+ m = TempSwP0Array[0];
+ for (i = 1; i < LogicalSocketCount; i++) {
+ CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader);
+ if ((PStateBufferPtrTmp->PStateCoreStruct[0].PStateMaxValue != PStateBufferPtr[0].PStateCoreStruct[0].PStateMaxValue)) {
+ TempFlag1 = TRUE;
+ break;
+ }
+ MaxPstateInNode = PStateBufferPtrTmp->PStateCoreStruct[0].PStateMaxValue;
+ for (k = TempSwP0Array[i]; k <= MaxPstateInNode; k++, m++) {
+ if ((PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[m].CoreFreq !=
+ PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[k].CoreFreq) ||
+ (PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[m].Power !=
+ PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[k].Power)) {
+ TempFlag1 = TRUE;
+ break; // Come out of the inner FOR loop
+ }
+ }
+ if (TempFlag1) {
+ break; // Come out of the outer FOR loop
+ }
+ }
+
+ if (!TempFlag1) {
+ // No need to do pStateLeveling, or writing to pState MSR registers
+ // if all CPUs have Identical PStates
+ PStateBufferPtr[0].AllCpusHaveIdenticalPStates = TRUE;
+ PStateBufferPtr[0].InitStruct = 1;
+ PutAllCoreInPState0 (PStateBufferPtr, StdHeader);
+ return AGESA_UNSUPPORTED;
+ } else {
+ PStateBufferPtr[0].AllCpusHaveIdenticalPStates = FALSE;
+ }
+
+ // 1_b) & 1_c)
+ TempFlag1 = FALSE;
+ TempFlag2 = FALSE;
+ for (i = 0; i < LogicalSocketCount; i++) {
+ CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader);
+ if (PStateBufferPtrTmp->PStateCoreStruct[0].PStateMaxValue == TempSwP0Array[i]) {
+ TempFlag1 = TRUE;
+ } else {
+ TempFlag2 = TRUE;
+ }
+ if (PStateBufferPtrTmp->PStateCoreStruct[0].HtcCapable == 0) {
+ TempFlag3 = TRUE;
+ } else {
+ TempFlag4 = TRUE;
+ }
+
+ if ((PStateBufferPtrTmp->PStateCoreStruct[0].PStateMaxValue -
+ PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit) < 2) {
+ PstateMaxValMinusHtcPstateLimitLessThan2Flag = TRUE;
+ }
+
+ if (PStateBufferPtrTmp->PStateCoreStruct[0].PStateMaxValue ==
+ PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit) {
+ PstateMaxValEquToPstateHtcLimitFlag = TRUE;
+ }
+
+ if (PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit == 1) {
+ AtLeastOneCoreHasPstateHtcLimitEquToOneFlag = TRUE;
+ }
+ }
+
+ // Do general setup of flags, that we may use later
+ // Implementation of (1_b)
+ if (TempFlag1 && TempFlag2) {
+ //
+ //Processors with only one enabled P-state (F3xDC[PstateMaxVal]=000b) cannot be mixed in a system with
+ //processors with more than one enabled P-state (F3xDC[PstateMaxVal]!=000b).
+ //
+ PStateBufferPtr[0].InitStruct = 1;
+ PStateBufferPtr[0].CreateAcpiTables = 0;
+ PutAllCoreInPState0 (PStateBufferPtr, StdHeader);
+ return AGESA_UNSUPPORTED;
+ } else if (TempFlag1 && !TempFlag2) {
+ //
+ //all processors have only 1 enabled P-state
+ //
+ AllCoreHaveMaxOnePStateFlag = TRUE;
+ PStateBufferPtr[0].OnlyOneEnabledPState = TRUE;
+ }
+
+ // Processors with F3xE8[HTC_CAPABLE] = 1 can not be
+ // mixed in system with processors with F3xE8[HTC_CAPABLE] = 0.
+ if (TempFlag3 && TempFlag4) {
+ PStateBufferPtr[0].InitStruct = 1;
+ for (i = 0; i < LogicalSocketCount; i++) {
+ CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader);
+ PStateBufferPtrTmp[0].CreateAcpiTables = 0;
+ }
+ PutAllCoreInPState0 (PStateBufferPtr, StdHeader);
+ return AGESA_UNSUPPORTED;
+ }
+
+ if (TempFlag3) {
+ //
+ //If code run to here means that all processors do not have HTC_CAPABLE.
+ //
+ AllCoresHaveHtcCapEquToZeroFlag = TRUE;
+ }
+
+ //--------------------------------------------------------------------------------
+ // S T E P - 2
+ //--------------------------------------------------------------------------------
+ // Now run the PState Leveling Algorithm which will create mixed CPU P-State
+ // Tables.
+ // Follow the algorithm in the latest BKDG
+ // -------------------------------------------------------------------------------
+ // Match P0 CPU COF for all CPU cores to the lowest P0 CPU COF value in the
+ // coherent fabric, and match P0 power for all CPU cores to the highest P0 power
+ // value in the coherent fabric.
+ // 2_a) If all processors have only 1 enabled P-State BIOS must write the
+ // appropriate CpuFid value resulting from the matched CPU COF to all
+ // copies of MSRC001_0070[CpuFid], and exit the sequence (No further
+ // steps are executed)
+ //--------------------------------------------------------------------------------
+ // Identify the lowest P0 Frequency and maximum P0 Power
+ TempVar_d = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempSwP0Array[0]].CoreFreq;
+ TempVar_e = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempSwP0Array[0]].Power;
+ TempVar_a = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempSwP0Array[0]].IddValue;
+ TempVar_b = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempSwP0Array[0]].IddDiv;
+
+ for (i = 0; i < LogicalSocketCount; i++) {
+ CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader);
+ if (TempVar_d > PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSwP0Array[i]].CoreFreq) {
+ TempVar_d = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSwP0Array[i]].CoreFreq;
+ }
+
+ if (TempVar_e < PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSwP0Array[i]].Power) {
+ TempVar_e = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSwP0Array[i]].Power;
+ TempVar_a = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSwP0Array[i]].IddValue;
+ TempVar_b = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSwP0Array[i]].IddDiv;
+ }
+ }
+
+ // Set P0 Frequency and Power for all CPUs
+ for (i = 0; i < LogicalSocketCount; i++) {
+ CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader);
+ PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSwP0Array[i]].CoreFreq = TempVar_d;
+ PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSwP0Array[i]].Power = TempVar_e;
+ PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSwP0Array[i]].IddValue = TempVar_a;
+ PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSwP0Array[i]].IddDiv = TempVar_b;
+ }
+
+ // 2_a)
+ if (!AllCoreHaveMaxOnePStateFlag) {
+ //--------------------------------------------------------------------------
+ // STEP - 3
+ //--------------------------------------------------------------------------
+ // Match the CPU COF and power for P-states used by HTC. Skip to step 4
+ // is any processor reports F3xE8[HTC_Capable] = 0;
+ // 3_a) Set F3x64[HtcPstateLimit] = 001b and F3x68[StcPstateLimit] = 001b for
+ // processors with F3x64[HtcPstateLimit] = 000b.
+ // 3_b) Identify the lowest CPU COF for all processors in the P-state
+ // pointed to by [The Hardware Thermal Control (HTC) Register]
+ // F3x64[HtcPstateLimit]
+ // 3_c) Modify the CPU COF pointed to by [The Hardware Thermal Control
+ // (HTC) Register] F3x64[HtcPstateLimit] for all processors to the
+ // previously identified lowest CPU COF value.
+ // 3_d) Identify the highest power for all processors in the P-state
+ // pointed to by [The Hardware Thermal Control (HTC) Register]
+ // F3x64[HtcPstateLimit].
+ // 3_e) Modify the power pointed to by [The Hardware Thermal Control (HTC)
+ // Register] F3x64[HtcPstateLimit] to the previously identified
+ // highest power value.
+ if (!AllCoresHaveHtcCapEquToZeroFlag) {
+ // 3_a)
+ for (i = 0; i < LogicalSocketCount; i++) {
+ CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader);
+ if (PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit == 0) {
+ // To Be Done (Set Htc and Stc PstateLimit values)
+ // for this CPU (using PCI address space)
+ for (k = 0; k < (UINT8)GetPlatformNumberOfModules (); k++) {
+ if (GetPciAddress (StdHeader, PStateBufferPtrTmp->SocketNumber, k, &PciAddress, &Status)) {
+ // Set F3x64[HtcPstateLimit] = 001b
+ PciAddress.Address.Function = FUNC_3;
+ PciAddress.Address.Register = HARDWARE_THERMAL_CTRL_REG;
+ LibAmdPciRead (AccessWidth32, PciAddress, &TempVar_d, StdHeader);
+ // Bits 30:28
+ TempVar_d = (TempVar_d & 0x8FFFFFFF) | 0x10000000;
+ LibAmdPciWrite (AccessWidth32, PciAddress, &TempVar_d, StdHeader);
+
+ // Set F3x68[StcPstateLimit] = 001b
+ PciAddress.Address.Register = SOFTWARE_THERMAL_CTRL_REG;
+ LibAmdPciRead (AccessWidth32, PciAddress, &TempVar_d, StdHeader);
+ // Bits 28:30
+ TempVar_d = (TempVar_d & 0x8FFFFFFF) | 0x10000000;
+ LibAmdPciWrite (AccessWidth32, PciAddress, &TempVar_d, StdHeader);
+ }
+ }
+ // Set LocalBuffer
+ PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit = 1;
+ if ((PStateBufferPtrTmp->PStateCoreStruct[0].PStateMaxValue - 1) < 2) {
+ PstateMaxValMinusHtcPstateLimitLessThan2Flag = TRUE;
+ }
+
+ if (PStateBufferPtrTmp->PStateCoreStruct[0].PStateMaxValue == 1) {
+ PstateMaxValEquToPstateHtcLimitFlag = TRUE;
+ }
+ }
+
+ if (PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit == 1) {
+ AtLeastOneCoreHasPstateHtcLimitEquToOneFlag = TRUE;
+ }
+ }
+
+ // 3_b) and 3_d)
+ TempVar_a = PStateBufferPtr[0].PStateCoreStruct[0].HtcPstateLimit;
+ TempVar_d = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempVar_a].CoreFreq;
+ TempVar_e = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempVar_a].Power;
+ TempVar_f = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempVar_a].IddValue;
+ TempVar_c = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempVar_a].IddDiv;
+ for (i = 0; i < LogicalSocketCount; i++) {
+ CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader);
+ for (k = 0; k < 1; k++) {
+ TempVar_b = PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit;
+ if (TempVar_d > PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_b].CoreFreq) {
+ TempVar_d = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_b].CoreFreq;
+ }
+
+ if (TempVar_e < PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_b].Power) {
+ TempVar_e = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_b].Power;
+ TempVar_f = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_b].IddValue;
+ TempVar_c = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_b].IddDiv;
+ }
+ }
+ }
+
+ // 3_c) and 3_e)
+ for (i = 0; i < LogicalSocketCount; i++) {
+ CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader);
+ TempVar_a = PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit;
+ PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_a].CoreFreq = TempVar_d;
+ PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_a].Power = TempVar_e;
+ PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_a].IddValue = TempVar_f;
+ PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_a].IddDiv = TempVar_c;
+ }
+ } // if(AllCoresHaveHtcCapEquToZeroFlag)
+
+
+ //--------------------------------------------------------------------------
+ // STEP - 4
+ //--------------------------------------------------------------------------
+ // Match the CPU COF and power for the lowest performance P-state:
+ // 4_a) If F3xDC[PstateMaxVal] = F3x64[HtcPstateLimit] for any processor,
+ // set PstateEn = 0 for all the P-states greater than
+ // F3x64[HtcPstateLimit] for all processors.
+ // 4_b) Identify the lowest CPU COF for all processors in the P-state
+ // pointed to by F3xDC[PstateMaxVal].
+ // 4_c) Modify the CPU COF for all processors in the P-state pointed to by
+ // F3xDC[PstateMaxVal] to the previously identified lowest CPU COF
+ // value.
+ // 4_d) Identify the highest power for all processors in the P-state
+ // pointed to by F3xDC[PstateMaxVal].
+ // 4_e) Modify the power for all processors in the P-state pointed to by
+ // F3xDC[PstateMaxVal] to the previously identified highest power
+ // value.
+
+ // 4_a)
+ if (PstateMaxValEquToPstateHtcLimitFlag) {
+ for (i = 0; i < LogicalSocketCount; i++) {
+ CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader);
+ TempVar_b = PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit + 1;
+ for (k = TempVar_b; k <= PStateBufferPtrTmp->PStateCoreStruct[0].PStateMaxValue; k++) {
+ PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[k].PStateEnable = 0;
+ }
+ //--------------------------------------------------------------------------
+ // STEP - 5
+ //--------------------------------------------------------------------------
+ // 5_a) Modify F3xDC[PstateMaxVal] to indicate the lowest performance
+ // P-state with PstateEn set for each processor (Step 4 can disable
+ // P-states pointed to by F3xDC[PstateMaxVal])
+
+ // Use this value of HtcPstateLimit to program the
+ // F3xDC[pStateMaxValue]
+ TempVar_e = PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit;
+ TempVar_e <<= 8;
+ // Bits 10:8
+
+ for (m = 0; m < (UINT8)GetPlatformNumberOfModules (); m++) {
+ if (GetPciAddress (StdHeader, PStateBufferPtrTmp->SocketNumber, m, &PciAddress, &Status)) {
+ PciAddress.Address.Function = FUNC_3;
+ PciAddress.Address.Register = CLOCK_POWER_TIMING_CTRL2_REG;
+ LibAmdPciRead (AccessWidth32, PciAddress, &TempVar_d, StdHeader);
+ TempVar_d = (TempVar_d & 0xFFFFF8FF) | TempVar_e;
+ LibAmdPciWrite (AccessWidth32, PciAddress, &TempVar_d, StdHeader);
+ }
+ }//End of step 5
+ }
+ }// End of 4_a)
+
+ // 4_b) and 4_d)
+ TempVar_a = PStateBufferPtr[0].PStateCoreStruct[0].PStateMaxValue;
+ TempVar_d = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempVar_a].CoreFreq;
+ TempVar_e = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempVar_a].Power;
+ TempVar_f = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempVar_a].IddValue;
+ TempVar_c = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempVar_a].IddDiv;
+
+ for (i = 0; i < LogicalSocketCount; i++) {
+ CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader);
+ TempVar_b = PStateBufferPtrTmp->PStateCoreStruct[0].PStateMaxValue;
+ if (TempVar_d >
+ PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_b].CoreFreq) {
+ TempVar_d =
+ PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_b].CoreFreq;
+ }
+
+ if (TempVar_e < PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_b].Power) {
+ TempVar_e = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_b].Power;
+ TempVar_f = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_b].IddValue;
+ TempVar_c = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_b].IddDiv;
+ }
+ }
+
+ // 4_c) and 4_e)
+ for (i = 0; i < LogicalSocketCount; i++) {
+ CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader);
+ TempVar_a = PStateBufferPtrTmp->PStateCoreStruct[0].PStateMaxValue;
+ PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_a].CoreFreq = TempVar_d;
+ PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_a].Power = TempVar_e;
+ PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_a].IddValue = TempVar_f;
+ PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_a].IddDiv = TempVar_c;
+ }
+
+
+ //--------------------------------------------------------------------------
+ // STEP - 6
+ //--------------------------------------------------------------------------
+ // Match the CPU COF and power for upper intermediate performance
+ // P-state(s):
+ // Upper intermediate PStates = PStates between (Not including) P0 and
+ // F3x64[HtcPstateLimit]
+ // 6_a) If F3x64[HtcPstateLimit] = 001b for any processor, set PstateEn = 0
+ // for enabled upper intermediate P-states for all processors with
+ // F3x64[HtcPstateLimit] > 001b and skip the remaining actions for
+ // this numbered step.
+ // 6_b) Define each of the available upper intermediate P-states; for each
+ // processor concurrently evaluate the following loop; when any
+ // processor falls out of the loop (runs out of available upper
+ // intermediate Pstates) all other processors have their remaining
+ // upper intermediate P-states invalidated (PstateEn = 0);
+ // for (i = F3x64[HtcPstateLimit] - 1; i > 0; i--)
+ // - Identify the lowest CPU COF for P(i).
+ // - Identify the highest power for P(i).
+ // - Modify P(i) CPU COF for all processors to the previously
+ // identified lowest CPU COF value.
+ // - Modify P(i) power for all processors to the previously
+ // identified highest power value.
+
+ // 6_a)
+ if (AtLeastOneCoreHasPstateHtcLimitEquToOneFlag) {
+ for (i = 0; i < LogicalSocketCount; i++) {
+ CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader);
+ for (k = TempSwP0Array[i] + 1; k < (PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit); k++) {
+ if (PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit > 1) {
+ // Make a function call to clear the
+ // structure values
+ PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[k].PStateEnable = 0;
+ }
+ }
+ }
+ }
+ // 6_b)
+ else {
+ // Identify Lowest Frequency and Highest Power
+ TotalIterations = 0;
+ TempFlag1 = TRUE;
+
+ for (i = 0; i < LogicalSocketCount; i++) {
+ CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader);
+ TempSocketPiArray[i] = PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit - 1;
+ }
+
+ do {
+ //For first socket, try to find a candidate
+ if (TempSocketPiArray[0] != TempSwP0Array[0]) {
+ while (PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempSocketPiArray[0]].PStateEnable == 0) {
+ TempSocketPiArray[0] = TempSocketPiArray[0] - 1;
+ if (TempSocketPiArray[0] == TempSwP0Array[0]) {
+ TempFlag1 = FALSE;
+ break;
+ }
+ }
+ } else {
+ TempFlag1 = FALSE;
+ }
+ if (TempFlag1) {
+ TempFreqArray[TotalIterations] = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempSocketPiArray[0]].CoreFreq;
+ TempPowerArray[TotalIterations] = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempSocketPiArray[0]].Power;
+ TempIddValueArray[TotalIterations] = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempSocketPiArray[0]].IddValue;
+ TempIddDivArray[TotalIterations] = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempSocketPiArray[0]].IddDiv;
+
+ //Try to find next candidate
+ for (i = 1; i < LogicalSocketCount; i++) {
+ CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader);
+ if (TempSocketPiArray[i] != TempSwP0Array[i]) {
+ while (PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].PStateEnable == 0) {
+ TempSocketPiArray[i]--;
+ if (TempSocketPiArray[i] == TempSwP0Array[i]) {
+ TempFlag1 = FALSE;
+ break;
+ }
+ }//end while
+ } else {
+ TempFlag1 = FALSE;
+ }
+
+ } //end for LogicalSocketCount
+ }
+
+ if (TempFlag1) {
+ for (i = 0; i < LogicalSocketCount; i++) {
+ //
+ //Compare
+ //
+ CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader);
+ if (TempFreqArray[TotalIterations] > PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].CoreFreq) {
+ TempFreqArray[TotalIterations] = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].CoreFreq;
+ }
+
+ if (TempPowerArray[TotalIterations] < PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].Power) {
+ TempPowerArray[TotalIterations] = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].Power;
+ TempIddValueArray[TotalIterations] = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].IddValue;
+ TempIddDivArray[TotalIterations] = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].IddDiv;
+ }
+ }
+ // Modify (Pi) CPU COF and Power for all the CPUs
+ for (i = 0; i < LogicalSocketCount; i++) {
+ CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader);
+ PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].CoreFreq = TempFreqArray[TotalIterations];
+ PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].Power = TempPowerArray[TotalIterations];
+ PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].IddValue = TempIddValueArray[TotalIterations];
+ PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].IddDiv = TempIddDivArray[TotalIterations];
+ TempSocketPiArray[i] = TempSocketPiArray[i] - 1;
+ }
+ } else {
+ for (i = 0; i < LogicalSocketCount; i++) {
+ CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader);
+ for (m = TempSocketPiArray[i]; m > TempSwP0Array[i]; m--) {
+ PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[m].PStateEnable = 0;
+ }
+ }
+ }
+
+ TotalIterations++;
+ } while (TempFlag1);
+
+ } // else
+
+ //--------------------------------------------------------------------------
+ // STEP - 7
+ //--------------------------------------------------------------------------
+ // Match the CPU COF and power for lower intermediate performance P - state(s)
+ // Lower Intermediate Pstates = Pstates between (not including)
+ // F3x64[HtcPstateLimit] and F3xDC[PstateMaxVal]
+ // 7_a) If F3xDC[PstateMaxVal] - F3x64[HtcPstateLimit] < 2 for any
+ // processor, set PstateEn = 0 for enabled lower intermediate P - states
+ // for all processors with (F3xDC[PstateMaxVal] -
+ // F3x64[HtcPstateLimit] > 1) and skip the remaining actions for this
+ // numbered step.
+ // 7_b) Define each of the available lower intermediate P-states; for each
+ // processor concurrently evaluate the following loop; when any
+ // processor falls out of the loop (runs out of available lower
+ // intermediate Pstates) all other processors have their remaining
+ // lower intermediate P-states invalidated (PstateEn = 0);
+ // for (i = F3xDC[PstateMaxVal]-1; i > F3x64[HtcPstateLimit]; i--)
+ // - Identify the lowest CPU COF for P-states between
+ // (not including) F3x64[HtcPstateLimit] and P(i).
+ // - Identify the highest power for P-states between
+ // (not including) F3x64[HtcPstateLimit] and P(i).
+ // - Modify P(i) CPU COF for all processors to the previously
+ // identified lowest CPU COF value.
+ // - Modify P(i) power for all processors to the previously
+ // identified highest power value.
+
+
+ // 7_a)
+ if (PstateMaxValMinusHtcPstateLimitLessThan2Flag) {
+ for (i = 0; i < LogicalSocketCount; i++) {
+ CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader);
+
+ for (k = PStateBufferPtrTmp->PStateCoreStruct[0].PStateMaxValue - 1;
+ k > PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit;
+ k--) {
+ if ((PStateBufferPtrTmp->PStateCoreStruct[0].PStateMaxValue -
+ PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit) > 1) {
+ PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[k].PStateEnable = 0;
+ }
+ }
+ }
+ }
+
+ // 7_b)
+ else {
+ // Identify Lowest Frequency and Highest Power
+
+ TotalIterations = 0;
+ TempFlag1 = TRUE;
+
+ for (i = 0; i < LogicalSocketCount; i++) {
+ CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader);
+ TempSocketPiArray[i] = PStateBufferPtrTmp->PStateCoreStruct[0].PStateMaxValue - 1;
+ }
+
+ do {
+ //For first socket, try to find a candidate
+ if (TempSocketPiArray[0] != PStateBufferPtr[0].PStateCoreStruct[0].HtcPstateLimit) {
+ while (PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempSocketPiArray[0]].PStateEnable == 0) {
+ TempSocketPiArray[0] = TempSocketPiArray[0] - 1;
+ if (TempSocketPiArray[0] == PStateBufferPtr[0].PStateCoreStruct[0].HtcPstateLimit) {
+ TempFlag1 = FALSE;
+ break;
+ }
+ }
+ } else {
+ TempFlag1 = FALSE;
+ }
+ if (TempFlag1) {
+ TempFreqArray[TotalIterations] = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempSocketPiArray[0]].CoreFreq;
+ TempPowerArray[TotalIterations] = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempSocketPiArray[0]].Power;
+ TempIddValueArray[TotalIterations] = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempSocketPiArray[0]].IddValue;
+ TempIddDivArray[TotalIterations] = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempSocketPiArray[0]].IddDiv;
+
+ //Try to find next candidate
+ for (i = 1; i < LogicalSocketCount; i++) {
+ CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader);
+ if (TempSocketPiArray[i] != PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit) {
+ while (PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].PStateEnable == 0) {
+ TempSocketPiArray[i]--;
+ if (TempSocketPiArray[i] == PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit) {
+ TempFlag1 = FALSE;
+ break;
+ }
+ }//end while
+ } else {
+ TempFlag1 = FALSE;
+ }
+ } //end for LogicalSocketCount
+ }
+
+ if (TempFlag1) {
+ for (i = 0; i < LogicalSocketCount; i++) {
+ //
+ //Compare
+ //
+ CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader);
+ if (TempFreqArray[TotalIterations] > PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].CoreFreq) {
+ TempFreqArray[TotalIterations] = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].CoreFreq;
+ }
+ if (TempPowerArray[TotalIterations] < PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].Power) {
+ TempPowerArray[TotalIterations] = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].Power;
+ TempIddValueArray[TotalIterations] = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].IddValue;
+ TempIddDivArray[TotalIterations] = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].IddDiv;
+ }
+ }
+ // Modify (Pi) CPU COF and Power for all the CPUs
+ for (i = 0; i < LogicalSocketCount; i++) {
+ CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader);
+ PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].CoreFreq = TempFreqArray[TotalIterations];
+ PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].Power = TempPowerArray[TotalIterations];
+ PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].IddValue = TempIddValueArray[TotalIterations];
+ PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].IddDiv = TempIddDivArray[TotalIterations];
+ TempSocketPiArray[i] = TempSocketPiArray[i] - 1;
+ }
+ } else {
+ for (i = 0; i < LogicalSocketCount; i++) {
+ CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader);
+ for (m = TempSocketPiArray[i]; m > PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit; m--) {
+ PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[m].PStateEnable = 0;
+ }
+ }
+ }
+ TotalIterations++;
+ } while (TempFlag1);
+ } // else
+ } // if(!AllCoreHaveMaxOnePStateFlag)
+
+ PStateBufferPtr[0].InitStruct = 1;
+ } // CurrentCore
+
+
+ // Update the pState MSRs
+ // This can be done only by individual core
+ StartPstateMsrModify (PStateStrucPtr, StdHeader);
+
+ //----------------------------------------------------------------------------------
+ // STEP - 8
+ //----------------------------------------------------------------------------------
+ // Place all cores into a valid COF and VID configuration corresponding to an
+ // enabled P-state:
+ // 8_a) Select an enabled P-state != to the P-state pointed to by
+ // MSRC001_0063[CurPstate] for each core.
+ // 8_b) Transition all cores to the selected P-states by writing the Control value
+ // from the_PSS object corresponding to the selected P-state to
+ // MSRC001_0062[PstateCmd].
+ // 8_c) Wait for all cores to report the Status value from the _PSS object
+ // corresponding to the selected P-state in MSRC001_0063[CurPstate].
+ //
+ PutAllCoreInPState0 (PStateBufferPtr, StdHeader);
+
+ return AGESA_SUCCESS;
+}
+
+
+/*----------------------------------------------------------------------------
+ * LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/**
+ *---------------------------------------------------------------------------------------
+ *
+ * PutAllCoreInPState0
+ *
+ * Description:
+ * This function will put core pstate to p0.
+ *
+ * Parameters:
+ * @param[in,out] *PStateBufferPtr
+ * @param[in] *StdHeader
+ *
+ * @retval AGESA_STATUS
+ *
+ *---------------------------------------------------------------------------------------
+ **/
+AGESA_STATUS
+PutAllCoreInPState0 (
+ IN OUT PSTATE_LEVELING *PStateBufferPtr,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ AP_TASK TaskPtr;
+ UINT32 BscSocket;
+ UINT32 Ignored;
+ UINT32 BscCoreNum;
+ UINT32 Core;
+ UINT32 Socket;
+ UINT32 NumberOfSockets;
+ UINT32 NumberOfCores;
+ AGESA_STATUS IgnoredSts;
+
+ TaskPtr.FuncAddress.PfApTaskI = PutCoreInPState0;
+ TaskPtr.DataTransfer.DataSizeInDwords = SIZE_IN_DWORDS (PSTATE_LEVELING);
+ TaskPtr.ExeFlags = WAIT_FOR_CORE;
+ TaskPtr.DataTransfer.DataPtr = PStateBufferPtr;
+ TaskPtr.DataTransfer.DataTransferFlags = DATA_IN_MEMORY;
+
+ IdentifyCore (StdHeader, &BscSocket, &Ignored, &BscCoreNum, &IgnoredSts);
+ NumberOfSockets = GetPlatformNumberOfSockets ();
+
+ PutCoreInPState0 (PStateBufferPtr, StdHeader);
+
+ for (Socket = 0; Socket < NumberOfSockets; Socket++) {
+ if (GetActiveCoresInGivenSocket (Socket, &NumberOfCores, StdHeader)) {
+ for (Core = 0; Core < NumberOfCores; Core++) {
+ if ((Socket != (UINT32) BscSocket) || (Core != (UINT32) BscCoreNum)) {
+ ApUtilRunCodeOnSocketCore ((UINT8) Socket, (UINT8) Core, &TaskPtr, StdHeader);
+ }
+ }
+ }
+ }
+
+ return AGESA_SUCCESS;
+}
+
+/**
+ *---------------------------------------------------------------------------------------
+ *
+ * CorePstateRegModify
+ *
+ * Description:
+ * This function will setting the Pstate MSR to each APs base on Pstate Buffer.
+ * Note: This function should be called for every core in the system.
+ *
+ * Parameters:
+ * @param[in,out] *CpuAmdPState
+ * @param[in] *StdHeader
+ *
+ * @retval VOID
+ *
+ *---------------------------------------------------------------------------------------
+ **/
+VOID
+CorePstateRegModify (
+ IN VOID *CpuAmdPState,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ PSTATE_CPU_FAMILY_SERVICES *FamilySpecificServices;
+ FamilySpecificServices = NULL;
+
+ GetFeatureServicesOfCurrentCore (&PstateFamilyServiceTable, (CONST VOID **)&FamilySpecificServices, StdHeader);
+ ASSERT (FamilySpecificServices != NULL)
+ FamilySpecificServices->SetPStateLevelReg (FamilySpecificServices, (S_CPU_AMD_PSTATE *) CpuAmdPState, StdHeader);
+}
+
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * This function will set msr on all cores of all nodes.
+ *
+ * @param[in] CpuAmdPState Pointer to S_CPU_AMD_PSTATE.
+ * @param[in] StdHeader Header for library and services.
+ *
+ * @retval AGESA_SUCCESS Always succeeds
+ *
+ */
+AGESA_STATUS
+StartPstateMsrModify (
+ IN S_CPU_AMD_PSTATE *CpuAmdPState,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ AP_TASK TaskPtr;
+ UINT32 BscSocket;
+ UINT32 Ignored;
+ UINT32 BscCoreNum;
+ UINT32 Core;
+ UINT32 Socket;
+ UINT32 NumberOfSockets;
+ UINT32 NumberOfCores;
+ AGESA_STATUS IgnoredSts;
+
+ TaskPtr.FuncAddress.PfApTaskI = CorePstateRegModify;
+ TaskPtr.DataTransfer.DataSizeInDwords = (UINT16) (CpuAmdPState->SizeOfBytes / 4 + 1);
+ TaskPtr.ExeFlags = WAIT_FOR_CORE;
+ TaskPtr.DataTransfer.DataPtr = CpuAmdPState;
+ TaskPtr.DataTransfer.DataTransferFlags = DATA_IN_MEMORY;
+
+ IdentifyCore (StdHeader, &BscSocket, &Ignored, &BscCoreNum, &IgnoredSts);
+ NumberOfSockets = GetPlatformNumberOfSockets ();
+
+ CorePstateRegModify (CpuAmdPState, StdHeader);
+
+ for (Socket = 0; Socket < NumberOfSockets; Socket++) {
+ if (GetActiveCoresInGivenSocket (Socket, &NumberOfCores, StdHeader)) {
+ for (Core = 0; Core < NumberOfCores; Core++) {
+ if ((Socket != (UINT32) BscSocket) || (Core != (UINT32) BscCoreNum)) {
+ ApUtilRunCodeOnSocketCore ((UINT8) Socket, (UINT8) Core, &TaskPtr, StdHeader);
+ }
+ }
+ }
+ }
+
+ return AGESA_SUCCESS;
+}
+
+
+/**
+ *---------------------------------------------------------------------------------------
+ *
+ * CpuGetPStateLevelStructure
+ *
+ * Description:
+ * Based on the LogicalSocketNumber, this function will return a pointer
+ * point to the accurate offset of the PSTATE_LEVELING structure.
+ *
+ * Parameters:
+ * @param[in,out] *PStateBufferPtr
+ * @param[in] *CpuAmdPState
+ * @param[in] LogicalSocketNumber
+ * @param[in] *StdHeader
+ *
+ * @retval VOID
+ *
+ *---------------------------------------------------------------------------------------
+ **/
+AGESA_STATUS
+CpuGetPStateLevelStructure (
+ OUT PSTATE_LEVELING **PStateBufferPtr,
+ IN S_CPU_AMD_PSTATE *CpuAmdPState,
+ IN UINT32 LogicalSocketNumber,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ PSTATE_LEVELING *PStateBufferPtrTmp;
+ UINT32 i;
+
+ if (LogicalSocketNumber > CpuAmdPState->TotalSocketInSystem) {
+ return AGESA_UNSUPPORTED;
+ }
+
+ PStateBufferPtrTmp = CpuAmdPState->PStateLevelingStruc;
+
+ for (i = 1; i <= LogicalSocketNumber; i++) {
+ PStateBufferPtrTmp = (PSTATE_LEVELING *) ((UINT8 *) PStateBufferPtrTmp + ((UINTN) PStateBufferPtrTmp->PStateLevelingSizeOfBytes));
+ }
+
+ *PStateBufferPtr = PStateBufferPtrTmp;
+
+ return AGESA_SUCCESS;
+}
+
+
+/**
+ *---------------------------------------------------------------------------------------
+ *
+ * PutCoreInPState0
+ *
+ * Description:
+ * This function will take the CPU core into P0
+ *
+ * Parameters:
+ * @param[in] *PStateBuffer
+ * @param[in] *StdHeader
+ *
+ * @retval VOID
+ *
+ *---------------------------------------------------------------------------------------
+ **/
+VOID
+STATIC
+PutCoreInPState0 (
+ IN VOID *PStateBuffer,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ CPU_SPECIFIC_SERVICES *FamilySpecificServices;
+ PSTATE_LEVELING *PStateBufferPtr;
+
+ PStateBufferPtr = (PSTATE_LEVELING *) PStateBuffer;
+
+ if ((PStateBufferPtr[0].SetPState0 == PSTATE_FLAG_1 ) ||
+ (PStateBufferPtr[0].SetPState0 == PSTATE_FLAG_2)) {
+ return;
+ }
+
+ GetCpuServicesOfCurrentCore ((CONST CPU_SPECIFIC_SERVICES **)&FamilySpecificServices, StdHeader);
+
+ FamilySpecificServices->TransitionPstate (FamilySpecificServices, (UINT8) 0, (BOOLEAN) FALSE, StdHeader);
+}
diff --git a/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuPstateTables.c b/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuPstateTables.c
new file mode 100644
index 0000000000..3be6fea352
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuPstateTables.c
@@ -0,0 +1,940 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * AMD PSTATE, ACPI table related API functions.
+ *
+ * Contains code that generates the _PSS, _PCT, and other ACPI tables.
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: CPU
+ * @e \$Revision: 84150 $ @e \$Date: 2012-12-12 15:46:25 -0600 (Wed, 12 Dec 2012) $
+ *
+ */
+/*****************************************************************************
+ *
+ * Copyright (c) 2008 - 2013, Advanced Micro Devices, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Advanced Micro Devices, Inc. nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ ******************************************************************************
+ */
+
+
+/*
+ *----------------------------------------------------------------------------
+ * MODULES USED
+ *
+ *----------------------------------------------------------------------------
+ */
+#include "AGESA.h"
+#include "amdlib.h"
+#include "OptionPstate.h"
+#include "cpuLateInit.h"
+#include "cpuRegisters.h"
+#include "cpuFamilyTranslation.h"
+#include "GeneralServices.h"
+#include "cpuServices.h"
+#include "heapManager.h"
+#include "Ids.h"
+#include "Filecode.h"
+#include "GeneralServices.h"
+#include "cpuPstateTables.h"
+#include "cpuFeatures.h"
+#include "cpuIoCstate.h"
+CODE_GROUP (G3_DXE)
+RDATA_GROUP (G3_DXE)
+
+#define FILECODE PROC_CPU_FEATURE_CPUPSTATETABLES_FILECODE
+/*----------------------------------------------------------------------------
+ * DEFINITIONS AND MACROS
+ *
+ *----------------------------------------------------------------------------
+ */
+extern OPTION_PSTATE_LATE_CONFIGURATION OptionPstateLateConfiguration; // global user config record
+extern CPU_FAMILY_SUPPORT_TABLE PstateFamilyServiceTable;
+extern CPU_FAMILY_SUPPORT_TABLE IoCstateFamilyServiceTable;
+
+STATIC ACPI_TABLE_HEADER ROMDATA CpuSsdtHdrStruct =
+{
+ {'S','S','D','T'},
+ 0,
+ 1,
+ 0,
+ {0},
+ {0},
+ 1,
+ {'A','M','D',' '},
+ 1
+};
+
+
+/*----------------------------------------------------------------------------
+ * TYPEDEFS AND STRUCTURES
+ *
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+ * PROTOTYPES OF LOCAL FUNCTIONS
+ *
+ *----------------------------------------------------------------------------
+ */
+UINT32
+STATIC
+CalAcpiTablesSize (
+ IN S_CPU_AMD_PSTATE *AmdPstatePtr,
+ IN PLATFORM_CONFIGURATION *PlatformConfig,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ );
+
+AGESA_STATUS
+GenerateSsdtStub (
+ IN AMD_CONFIG_PARAMS *StdHeader,
+ IN PLATFORM_CONFIGURATION *PlatformConfig,
+ IN OUT VOID **SsdtPtr
+ );
+
+UINT32
+CreateAcpiTablesStub (
+ IN PLATFORM_CONFIGURATION *PlatformConfig,
+ IN PSTATE_LEVELING *PStateLevelingBuffer,
+ IN OUT VOID **SsdtPtr,
+ IN UINT8 LocalApicId,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ );
+
+UINT32
+CreatePStateAcpiTables (
+ IN PLATFORM_CONFIGURATION *PlatformConfig,
+ IN PSTATE_LEVELING *PStateLevelingBuffer,
+ IN OUT VOID **SsdtPtr,
+ IN UINT8 LocalApicId,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ );
+
+UINT32
+CreateCStateAcpiTables (
+ IN PLATFORM_CONFIGURATION *PlatformConfig,
+ IN PSTATE_LEVELING *PStateLevelingBuffer,
+ IN OUT VOID **SsdtPtr,
+ IN UINT8 LocalApicId,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ );
+
+AGESA_STATUS
+GenerateSsdt (
+ IN AMD_CONFIG_PARAMS *StdHeader,
+ IN PLATFORM_CONFIGURATION *PlatformConfig,
+ IN OUT VOID **SsdtPtr
+ );
+
+/**
+ *---------------------------------------------------------------------------------------
+ *
+ * CalAcpiTablesSize
+ *
+ * Description:
+ * This function will calculate the size of ACPI PState tables
+ *
+ * Parameters:
+ * @param[in] *AmdPstatePtr
+ * @param[in] *PlatformConfig
+ * @param[in] *StdHeader
+ *
+ * @retval UINT32
+ *
+ *---------------------------------------------------------------------------------------
+ */
+UINT32
+STATIC
+CalAcpiTablesSize (
+ IN S_CPU_AMD_PSTATE *AmdPstatePtr,
+ IN PLATFORM_CONFIGURATION *PlatformConfig,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ UINT32 ScopeSize;
+ UINT32 CoreCount;
+ UINT32 SocketCount;
+ UINT32 MaxCoreNumberInCurrentSocket;
+ UINT32 MaxSocketNumberInSystem;
+ UINT32 MaxPstateNumberInCurrentCore;
+ UINT32 CstateAcpiObjSize;
+ PSTATE_LEVELING *PStateLevelingBufferStructPtr;
+ IO_CSTATE_FAMILY_SERVICES *IoCstateFamilyServices;
+
+ ScopeSize = sizeof (ACPI_TABLE_HEADER);
+ CstateAcpiObjSize = 0;
+ IoCstateFamilyServices = NULL;
+
+ PStateLevelingBufferStructPtr = AmdPstatePtr->PStateLevelingStruc;
+ MaxSocketNumberInSystem = AmdPstatePtr->TotalSocketInSystem;
+
+ if (IsFeatureEnabled (IoCstate, PlatformConfig, StdHeader)) {
+ GetFeatureServicesOfCurrentCore (&IoCstateFamilyServiceTable, (CONST VOID **)&IoCstateFamilyServices, StdHeader);
+ if (IoCstateFamilyServices != NULL) {
+ CstateAcpiObjSize = IoCstateFamilyServices->GetAcpiCstObj (IoCstateFamilyServices, PlatformConfig, StdHeader);
+ }
+ }
+
+ for (SocketCount = 0; SocketCount < MaxSocketNumberInSystem; SocketCount++) {
+ MaxCoreNumberInCurrentSocket = PStateLevelingBufferStructPtr->TotalCoresInNode;
+ for (CoreCount = 0; CoreCount < MaxCoreNumberInCurrentSocket; CoreCount++) {
+ MaxPstateNumberInCurrentCore = PStateLevelingBufferStructPtr->PStateCoreStruct[0].PStateMaxValue + 1;
+
+ ScopeSize += (SCOPE_STRUCT_SIZE - 1); // Scope size per core
+ ScopeSize += CstateAcpiObjSize; // C-State ACPI objects size per core
+
+ // Add P-State ACPI Objects size per core
+ if ((PStateLevelingBufferStructPtr[0].CreateAcpiTables != 0) && (PlatformConfig->UserOptionPState)) {
+ ScopeSize += (PCT_STRUCT_SIZE +
+ PSS_HEADER_STRUCT_SIZE +
+ (MaxPstateNumberInCurrentCore * PSS_BODY_STRUCT_SIZE) +
+ XPSS_HEADER_STRUCT_SIZE +
+ (MaxPstateNumberInCurrentCore * XPSS_BODY_STRUCT_SIZE) +
+ PSD_HEADER_STRUCT_SIZE +
+ PSD_BODY_STRUCT_SIZE +
+ PPC_HEADER_BODY_STRUCT_SIZE);
+ }
+ }
+ ScopeSize += MaxCoreNumberInCurrentSocket;
+ PStateLevelingBufferStructPtr = (PSTATE_LEVELING *) ((UINT8 *) PStateLevelingBufferStructPtr + (UINTN) sizeof (PSTATE_LEVELING) + (UINTN) (PStateLevelingBufferStructPtr->PStateCoreStruct[0].PStateMaxValue * sizeof (S_PSTATE_VALUES)));
+ }
+ AmdPstatePtr->SizeOfBytes = ScopeSize;
+
+ return ScopeSize;
+}
+
+/**--------------------------------------------------------------------------------------
+ *
+ * GenerateSsdtStub
+ *
+ * Description:
+ * This is the default routine for use when both PState and CState option is NOT
+ * requested. The option install process will create and fill the transfer vector
+ * with the address of the proper routine (Main or Stub). The link optimizer will
+ * strip out of the .DLL the routine that is not used.
+ *
+ * Parameters:
+ * @param[in] StdHeader Handle to config for library and services
+ * @param[in] PlatformConfig Contains the power cap parameter
+ * @param[in,out] SsdtPtr ACPI SSDT table pointer
+ *
+ * @retval AGESA_STATUS
+ *
+ *---------------------------------------------------------------------------------------
+ **/
+AGESA_STATUS
+GenerateSsdtStub (
+ IN AMD_CONFIG_PARAMS *StdHeader,
+ IN PLATFORM_CONFIGURATION *PlatformConfig,
+ IN OUT VOID **SsdtPtr
+ )
+{
+ return AGESA_UNSUPPORTED;
+}
+
+/**
+ *---------------------------------------------------------------------------------------
+ *
+ * GenerateSsdt
+ *
+ * Description:
+ * This function will populate the SSDT with ACPI P-States and C-States Objects, whenever
+ * necessary
+ * This function should be called only from BSP
+ *
+ * Parameters:
+ * @param[in] StdHeader Handle to config for library and services
+ * @param[in] PlatformConfig Contains the power cap parameter
+ * @param[in,out] SsdtPtr ACPI SSDT pointer
+ *
+ * @retval AGESA_STATUS
+ *
+ *---------------------------------------------------------------------------------------
+ */
+AGESA_STATUS
+GenerateSsdt (
+ IN AMD_CONFIG_PARAMS *StdHeader,
+ IN PLATFORM_CONFIGURATION *PlatformConfig,
+ IN OUT VOID **SsdtPtr
+ )
+{
+ UINT32 i;
+ UINT32 j;
+ UINT32 TempVar8_a;
+ UINT32 CurrSize;
+ UINT32 TempVar_a;
+ UINT32 TempVar_b;
+ UINT32 ScopeSize;
+ UINT32 CoreCount;
+ UINT32 SocketCount;
+ UINT32 MaxCorePerNode;
+ UINT8 LocalApicId;
+ UINT8 *IntermediatePtr;
+ AGESA_STATUS AgesaStatus;
+ LOCATE_HEAP_PTR LocateHeapParams;
+ ALLOCATE_HEAP_PARAMS AllocateHeapParams;
+ S_CPU_AMD_PSTATE *AmdPstatePtr;
+ PSTATE_LEVELING *PStateLevelingBufferStructPtr;
+ SCOPE *ScopeAcpiTablesStructPtr;
+ SCOPE *ScopeAcpiTablesStructPtrTemp;
+
+ AGESA_TESTPOINT (TpProcCpuEntryPstate, StdHeader);
+
+ ASSERT (IsBsp (StdHeader, &AgesaStatus));
+
+ // If P-State and C-State ACPI tables do not need to be generated, exit this routine
+ if ((!PlatformConfig->UserOptionPState) && (!IsFeatureEnabled (IoCstate, PlatformConfig, StdHeader))) {
+ AgesaStatus = AGESA_UNSUPPORTED;
+ return AgesaStatus;
+ }
+
+ // Initialize data variables
+ ScopeSize = 0;
+ CoreCount = 0;
+ LocalApicId = 0;
+ CurrSize = 0;
+
+ // Locate P-State data buffer
+ LocateHeapParams.BufferHandle = AMD_PSTATE_DATA_BUFFER_HANDLE;
+ AGESA_TESTPOINT (TpProcCpuBeforeLocateSsdtBuffer, StdHeader);
+ if (HeapLocateBuffer (&LocateHeapParams, StdHeader) != AGESA_SUCCESS) {
+ return AGESA_ERROR;
+ }
+ AGESA_TESTPOINT (TpProcCpuAfterLocateSsdtBuffer, StdHeader);
+
+ AmdPstatePtr = (S_CPU_AMD_PSTATE *) LocateHeapParams.BufferPtr;
+ PStateLevelingBufferStructPtr = AmdPstatePtr->PStateLevelingStruc;
+
+ // Allocate rough buffer for AcpiTable, if SsdtPtr is NULL
+ if (*SsdtPtr == NULL) {
+ //Do not know the actual size.. pre-calculate it.
+ AllocateHeapParams.RequestedBufferSize = CalAcpiTablesSize (AmdPstatePtr, PlatformConfig, StdHeader);
+ AllocateHeapParams.BufferHandle = AMD_PSTATE_ACPI_BUFFER_HANDLE;
+ AllocateHeapParams.Persist = HEAP_SYSTEM_MEM;
+
+ AGESA_TESTPOINT (TpProcCpuBeforeAllocateSsdtBuffer, StdHeader);
+ if (HeapAllocateBuffer (&AllocateHeapParams, StdHeader) != AGESA_SUCCESS) {
+ return AGESA_ERROR;
+ }
+ AGESA_TESTPOINT (TpProcCpuAfterAllocateSsdtBuffer, StdHeader);
+ *SsdtPtr = AllocateHeapParams.BufferPtr;
+ }
+
+ IDS_HDT_CONSOLE (CPU_TRACE, " SSDT is created\n");
+
+ // Copy SSDT header into allocated buffer
+ LibAmdMemCopy (*SsdtPtr, (VOID *) &CpuSsdtHdrStruct, (UINTN) (sizeof (ACPI_TABLE_HEADER)), StdHeader);
+ // Update table OEM fields.
+ LibAmdMemCopy ((VOID *) ((ACPI_TABLE_HEADER *) *SsdtPtr)->OemId, (VOID *) &OptionPstateLateConfiguration.OemIdString,
+ sizeof (OptionPstateLateConfiguration.OemIdString), StdHeader);
+ LibAmdMemCopy ((VOID *) ((ACPI_TABLE_HEADER *) *SsdtPtr)->OemTableId, (VOID *) &OptionPstateLateConfiguration.OemTableIdString,
+ sizeof (OptionPstateLateConfiguration.OemTableIdString), StdHeader);
+ IntermediatePtr = (UINT8 *) *SsdtPtr;
+ ScopeAcpiTablesStructPtr = (SCOPE *) &IntermediatePtr[sizeof (ACPI_TABLE_HEADER)];
+
+ SocketCount = AmdPstatePtr->TotalSocketInSystem;
+
+ // Generate name scope and ACPI objects for every core in the system
+ for (i = 0; i < SocketCount; i++) {
+ MaxCorePerNode = PStateLevelingBufferStructPtr->TotalCoresInNode;
+ for (j = 0; j < MaxCorePerNode; j++) {
+ CoreCount++;
+ // Set Name Scope for CPU0, 1, 2, ..... n
+ // CPU0 to CPUn will name as C000 to Cnnn
+ // -----------------------------------------
+ ScopeAcpiTablesStructPtr->ScopeOpcode = SCOPE_OPCODE;
+ // This value will be filled at the end of this function
+ // Since at this time, we don't know how many Pstates we
+ // would have
+ ScopeAcpiTablesStructPtr->ScopeLength = 0;
+ ScopeAcpiTablesStructPtr->ScopeValue1 = SCOPE_VALUE1;
+ ScopeAcpiTablesStructPtr->ScopeValue2 = SCOPE_VALUE2;
+ ScopeAcpiTablesStructPtr->ScopeNamePt1a__ = SCOPE_NAME__;
+ if (PlatformConfig->ProcessorScopeInSb) {
+ ScopeAcpiTablesStructPtr->ScopeNamePt1a_P = SCOPE_NAME_S;
+ ScopeAcpiTablesStructPtr->ScopeNamePt1a_R = SCOPE_NAME_B;
+ } else {
+ ScopeAcpiTablesStructPtr->ScopeNamePt1a_P = SCOPE_NAME_P;
+ ScopeAcpiTablesStructPtr->ScopeNamePt1a_R = SCOPE_NAME_R;
+ }
+ ScopeAcpiTablesStructPtr->ScopeNamePt1b__ = SCOPE_NAME__;
+ ASSERT ((PlatformConfig->ProcessorScopeName0 >= 'A') && (PlatformConfig->ProcessorScopeName0 <= 'Z'));
+ ASSERT (((PlatformConfig->ProcessorScopeName1 >= 'A') && (PlatformConfig->ProcessorScopeName1 <= 'Z')) || \
+ ((PlatformConfig->ProcessorScopeName1 >= '0') && (PlatformConfig->ProcessorScopeName1 <= '9')) || \
+ (PlatformConfig->ProcessorScopeName1 == '_'));
+
+ ScopeAcpiTablesStructPtr->ScopeNamePt2a_C = PlatformConfig->ProcessorScopeName0;
+ ScopeAcpiTablesStructPtr->ScopeNamePt2a_P = PlatformConfig->ProcessorScopeName1;
+
+ TempVar8_a = ((CoreCount - 1) >> 4) & 0x0F;
+ ScopeAcpiTablesStructPtr->ScopeNamePt2a_U = (UINT8) (SCOPE_NAME_0 + TempVar8_a);
+
+ TempVar8_a = (CoreCount - 1) & 0x0F;
+ if (TempVar8_a < 0xA) {
+ ScopeAcpiTablesStructPtr->ScopeNamePt2a_0 = (UINT8) (SCOPE_NAME_0 + TempVar8_a);
+ } else {
+ ScopeAcpiTablesStructPtr->ScopeNamePt2a_0 = (UINT8) (SCOPE_NAME_A + TempVar8_a - 0xA);
+ }
+ // Increment and typecast the pointer
+ ScopeAcpiTablesStructPtrTemp = ScopeAcpiTablesStructPtr;
+ ScopeAcpiTablesStructPtrTemp++;
+
+ // Get the Local Apic Id for each core
+ LocalApicId = PStateLevelingBufferStructPtr->PStateCoreStruct[0].LocalApicId + (UINT8) j;
+
+ // Create P-State ACPI Objects
+ CurrSize += ((*(OptionPstateLateConfiguration.PstateFeature)) (PlatformConfig, PStateLevelingBufferStructPtr, (VOID *) &ScopeAcpiTablesStructPtrTemp, LocalApicId, StdHeader));
+
+ // Create C-State ACPI Objects
+ CurrSize += ((*(OptionPstateLateConfiguration.CstateFeature)) (PlatformConfig, PStateLevelingBufferStructPtr, (VOID *) &ScopeAcpiTablesStructPtrTemp, LocalApicId, StdHeader));
+
+ // Now update the SCOPE Length field
+ {
+ CurrSize += (SCOPE_STRUCT_SIZE - 1);
+ ScopeSize += CurrSize;
+
+ TempVar_b = ((CurrSize << 4) & 0x0000FF00);
+ TempVar_b |= ((CurrSize & 0x0000000F) | 0x00000040);
+ TempVar_a = TempVar_b;
+ ScopeAcpiTablesStructPtr->ScopeLength = (UINT16) TempVar_a;
+ CurrSize = 0;
+ }
+
+ ScopeAcpiTablesStructPtr = ScopeAcpiTablesStructPtrTemp;
+ }
+ //Calculate next node buffer address
+ PStateLevelingBufferStructPtr = (PSTATE_LEVELING *) ((UINT8 *) PStateLevelingBufferStructPtr + (UINTN) sizeof (PSTATE_LEVELING) + (UINTN) (PStateLevelingBufferStructPtr->PStateCoreStruct[0].PStateMaxValue * sizeof (S_PSTATE_VALUES)));
+ }
+ //Update SSDT header Checksum
+ ((ACPI_TABLE_HEADER *) *SsdtPtr)->TableLength = (ScopeSize + CoreCount + sizeof (ACPI_TABLE_HEADER));
+ ChecksumAcpiTable ((ACPI_TABLE_HEADER *) *SsdtPtr, StdHeader);
+
+ return AGESA_SUCCESS;
+}
+
+/**--------------------------------------------------------------------------------------
+ *
+ * CreateAcpiTablesStub
+ *
+ * Description:
+ * This is the default routine for use when the P-State or C-State option is NOT
+ * requested. The option install process will create and fill the transfer vector
+ * with the address of the proper routine (Main or Stub). The link optimizer will
+ * strip out of the .DLL the routine that is not used.
+ *
+ * Parameters:
+ * @param[in] PlatformConfig Platform operational characteristics; power cap
+ * @param[in] PStateLevelingBuffer Buffer that contains P-State Leveling information
+ * @param[in,out] SsdtPtr ACPI SSDT table pointer
+ * @param[in] LocalApicId Local Apic Id
+ * @param[in] StdHeader Handle to config for library and services
+ *
+ * @retval Size of generated ACPI objects
+ *
+ *---------------------------------------------------------------------------------------
+ **/
+UINT32
+CreateAcpiTablesStub (
+ IN PLATFORM_CONFIGURATION *PlatformConfig,
+ IN PSTATE_LEVELING *PStateLevelingBuffer,
+ IN OUT VOID **SsdtPtr,
+ IN UINT8 LocalApicId,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ return 0;
+}
+
+
+/**--------------------------------------------------------------------------------------
+ *
+ * CreatePStateAcpiTables
+ *
+ * Description:
+ * This is the common routine for creating ACPI P-State objects
+ *
+ * Parameters:
+ * @param[in] PlatformConfig Platform operational characteristics; power cap
+ * @param[in] PStateLevelingBuffer Buffer that contains P-State Leveling information
+ * @param[in,out] SsdtPtr ACPI SSDT table pointer
+ * @param[in] LocalApicId Local Apic Id
+ * @param[in] StdHeader Handle to config for library and services
+ *
+ * @retval Size of generated ACPI P-States objects
+ *
+ *---------------------------------------------------------------------------------------
+ **/
+UINT32
+CreatePStateAcpiTables (
+ IN PLATFORM_CONFIGURATION *PlatformConfig,
+ IN PSTATE_LEVELING *PStateLevelingBuffer,
+ IN OUT VOID **SsdtPtr,
+ IN UINT8 LocalApicId,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ UINT8 PstateCapLevelSupport;
+ UINT8 PStateMaxValueOnCurrentCore;
+ BOOLEAN PstateCapEnable;
+ BOOLEAN PstateCapLevelSupportDetermined;
+ BOOLEAN IsPsdDependent;
+ UINT32 k;
+ UINT32 TempVar_a;
+ UINT32 TempVar_b;
+ UINT32 TempVar_c;
+ UINT32 PstateCapInputMilliWatts;
+ UINT32 CurrSize;
+ UINT32 PstateCount;
+ UINT32 CoreCount1;
+ UINT32 TransAndBusMastLatency;
+ UINT32 EffectivePstatesPsdPolicy;
+ AGESA_STATUS IgnoredStatus;
+ PCI_ADDR PciAddress;
+ PCT_HEADER_BODY *pPctAcpiTables;
+ PSS_HEADER *pPssHeaderAcpiTables;
+ PSS_BODY *pPssBodyAcpiTables;
+ XPSS_HEADER *pXpssHeaderAcpiTables;
+ XPSS_BODY *pXpssBodyAcpiTables;
+ PSD_HEADER *pPsdHeaderAcpiTables;
+ PSD_BODY *pPsdBodyAcpiTables;
+ PPC_HEADER_BODY *pPpcAcpiTables;
+ PSTATE_CPU_FAMILY_SERVICES *FamilyServices;
+
+ CurrSize = 0;
+ PstateCount = 0;
+ PstateCapEnable = FALSE;
+ PstateCapLevelSupport = DEFAULT_PERF_PRESENT_CAP;
+ PstateCapLevelSupportDetermined = TRUE;
+ PstateCapInputMilliWatts = PlatformConfig->PowerCeiling;
+ ASSERT (PlatformConfig->PstatesPsdPolicy < PsdPolicyMax);
+
+ EffectivePstatesPsdPolicy = PlatformConfig->PstatesPsdPolicy;
+ // Runtime P-state dependence settings conflict check and consolidation
+ if (PlatformConfig->ForcePstateIndependent) {
+ switch (EffectivePstatesPsdPolicy) {
+ case PsdPolicyProcessorDefault:
+ // Consolidate P-state dependence setings
+ EffectivePstatesPsdPolicy = PsdPolicyIndependent;
+ break;
+ case PsdPolicyDependent:
+ // Ensure P-state dependence settings do not conflict
+ IDS_HDT_CONSOLE (CPU_TRACE, " P-state PSD dependence settings conflict between ForcePstateIndependent and PstatesPsdPolicy. PstatesPsdPolicy will take precedence.\n");
+ ASSERT (FALSE);
+ break;
+ case PsdPolicyIndependent:
+ // Do nothing. Two interfaces have the same setting.
+ break;
+ default:
+ // Invalid setting, overrides to processor default.
+ IDS_HDT_CONSOLE (CPU_TRACE, " P-state PSD dependence settings invalid! Override PstatesPsdPolicy to PsdPolicyProcessorDefault.\n");
+ EffectivePstatesPsdPolicy = PsdPolicyProcessorDefault;
+ break;
+ }
+ }
+
+ TransAndBusMastLatency = 0;
+
+ if ((PStateLevelingBuffer[0].CreateAcpiTables != 0) && (PlatformConfig->UserOptionPState)) {
+ pPctAcpiTables = (PCT_HEADER_BODY *) *SsdtPtr;
+
+ //Check Pstate Capability
+ if (PstateCapInputMilliWatts != 0) {
+ PstateCapEnable = TRUE;
+ PstateCapLevelSupportDetermined = FALSE;
+ }
+
+ PStateMaxValueOnCurrentCore = PStateLevelingBuffer->PStateCoreStruct[0].PStateMaxValue;
+ if (OptionPstateLateConfiguration.CfgPstatePct) {
+ // Set _PCT Table
+ // --------------
+ pPctAcpiTables->NameOpcode = NAME_OPCODE;
+ pPctAcpiTables->PctName_a__ = PCT_NAME__;
+ pPctAcpiTables->PctName_a_P = PCT_NAME_P;
+ pPctAcpiTables->PctName_a_C = PCT_NAME_C;
+ pPctAcpiTables->PctName_a_T = PCT_NAME_T;
+ pPctAcpiTables->Value1 = PCT_VALUE1;
+ pPctAcpiTables->Value2 = PCT_VALUE2;
+ pPctAcpiTables->Value3 = PCT_VALUE3;
+ pPctAcpiTables->GenericRegDescription1 = GENERIC_REG_DESCRIPTION;
+ pPctAcpiTables->Length1 = PCT_LENGTH;
+ pPctAcpiTables->AddressSpaceId1 = PCT_ADDRESS_SPACE_ID;
+ pPctAcpiTables->RegisterBitWidth1 = PCT_REGISTER_BIT_WIDTH;
+ pPctAcpiTables->RegisterBitOffset1 = PCT_REGISTER_BIT_OFFSET;
+ pPctAcpiTables->Reserved1 = PCT_RESERVED;
+ pPctAcpiTables->ControlRegAddressLo = PCT_CONTROL_REG_LO;
+ pPctAcpiTables->ControlRegAddressHi = PCT_CONTROL_REG_HI;
+ pPctAcpiTables->Value4 = PCT_VALUE4;
+ pPctAcpiTables->Value5 = PCT_VALUE5;
+ pPctAcpiTables->GenericRegDescription2 = GENERIC_REG_DESCRIPTION;
+ pPctAcpiTables->Length2 = PCT_LENGTH;
+ pPctAcpiTables->AddressSpaceId2 = PCT_ADDRESS_SPACE_ID;
+ pPctAcpiTables->RegisterBitWidth2 = PCT_REGISTER_BIT_WIDTH;
+ pPctAcpiTables->RegisterBitOffset2 = PCT_REGISTER_BIT_OFFSET;
+ pPctAcpiTables->Reserved2 = PCT_RESERVED;
+ pPctAcpiTables->StatusRegAddressLo = PCT_STATUS_REG_LO;
+ pPctAcpiTables->StatusRegAddressHi = PCT_STATUS_REG_HI;
+ pPctAcpiTables->Value6 = PCT_VALUE6;
+
+ // Increment and then typecast the pointer
+ pPctAcpiTables++;
+ CurrSize += PCT_STRUCT_SIZE;
+
+ *SsdtPtr = pPctAcpiTables;
+ } // end of OptionPstateLateConfiguration.CfgPstatePct
+
+ pPssHeaderAcpiTables = (PSS_HEADER *) pPctAcpiTables;
+ pPssBodyAcpiTables = (PSS_BODY *) pPctAcpiTables;
+ if (OptionPstateLateConfiguration.CfgPstatePss) {
+ // Set _PSS Header
+ // Note: Set pssLength and numOfItemsInPss later
+ //---------------------------------------------------
+ pPssHeaderAcpiTables->NameOpcode = NAME_OPCODE;
+ pPssHeaderAcpiTables->PssName_a__ = PSS_NAME__;
+ pPssHeaderAcpiTables->PssName_a_P = PSS_NAME_P;
+ pPssHeaderAcpiTables->PssName_a_S = PSS_NAME_S;
+ pPssHeaderAcpiTables->PssName_b_S = PSS_NAME_S;
+ pPssHeaderAcpiTables->PkgOpcode = PACKAGE_OPCODE;
+
+ pPssHeaderAcpiTables++;
+ pPssBodyAcpiTables = (PSS_BODY *) pPssHeaderAcpiTables;
+ // Restore the pPssHeaderAcpiTables
+ pPssHeaderAcpiTables--;
+
+ // Set _PSS Body
+ //---------------
+ PstateCount = 0;
+
+ // Calculate PCI address for socket only
+ GetPciAddress (StdHeader, (UINT32) PStateLevelingBuffer->SocketNumber, 0, &PciAddress, &IgnoredStatus);
+ TransAndBusMastLatency = 0;
+ GetFeatureServicesOfSocket (&PstateFamilyServiceTable, (UINT32) PStateLevelingBuffer->SocketNumber, (CONST VOID **)&FamilyServices, StdHeader);
+ ASSERT (FamilyServices != NULL);
+ FamilyServices->GetPstateLatency ( FamilyServices,
+ PStateLevelingBuffer,
+ &PciAddress,
+ &TransAndBusMastLatency,
+ StdHeader);
+
+ for (k = 0; k <= PStateMaxValueOnCurrentCore; k++) {
+ if (PStateLevelingBuffer->PStateCoreStruct[0].PStateStruct[k].PStateEnable != 0) {
+ pPssBodyAcpiTables->PkgOpcode = PACKAGE_OPCODE;
+ pPssBodyAcpiTables->PkgLength = PSS_PKG_LENGTH;
+ pPssBodyAcpiTables->NumOfElements = PSS_NUM_OF_ELEMENTS;
+ pPssBodyAcpiTables->DwordPrefixOpcode1 = DWORD_PREFIX_OPCODE;
+ pPssBodyAcpiTables->Frequency =
+ PStateLevelingBuffer->PStateCoreStruct[0].PStateStruct[k].CoreFreq;
+ pPssBodyAcpiTables->DwordPrefixOpcode2 = DWORD_PREFIX_OPCODE;
+ pPssBodyAcpiTables->Power =
+ PStateLevelingBuffer->PStateCoreStruct[0].PStateStruct[k].Power;
+
+ if (PstateCapEnable && (!PstateCapLevelSupportDetermined) && (PstateCapInputMilliWatts >= pPssBodyAcpiTables->Power)) {
+ PstateCapLevelSupport = (UINT8) PStateLevelingBuffer->PStateCoreStruct[0].PStateStruct[k].SwPstateNumber;
+ PstateCapLevelSupportDetermined = TRUE;
+ }
+
+ pPssBodyAcpiTables->DwordPrefixOpcode3 = DWORD_PREFIX_OPCODE;
+ pPssBodyAcpiTables->TransitionLatency = TransAndBusMastLatency;
+ pPssBodyAcpiTables->DwordPrefixOpcode4 = DWORD_PREFIX_OPCODE;
+ pPssBodyAcpiTables->BusMasterLatency = TransAndBusMastLatency;
+ pPssBodyAcpiTables->DwordPrefixOpcode5 = DWORD_PREFIX_OPCODE;
+ pPssBodyAcpiTables->Control =
+ PStateLevelingBuffer->PStateCoreStruct[0].PStateStruct[k].SwPstateNumber;
+ pPssBodyAcpiTables->DwordPrefixOpcode6 = DWORD_PREFIX_OPCODE;
+ pPssBodyAcpiTables->Status =
+ PStateLevelingBuffer->PStateCoreStruct[0].PStateStruct[k].SwPstateNumber;
+
+ pPssBodyAcpiTables++;
+ PstateCount++;
+ }
+ } // for (k = 0; k < MPPSTATE_MAXIMUM_STATES; k++)
+
+ if (PstateCapEnable && (!PstateCapLevelSupportDetermined)) {
+ PstateCapLevelSupport = PStateMaxValueOnCurrentCore;
+ }
+
+ // Set _PSS Header again
+ // Now Set pssLength and numOfItemsInPss
+ //---------------------------------------
+ TempVar_a = (PstateCount * PSS_BODY_STRUCT_SIZE) + 3;
+ TempVar_b = TempVar_a;
+ TempVar_c = ((TempVar_b << 4) & 0x0000FF00);
+ TempVar_c = TempVar_c | ((TempVar_b & 0x0000000F) | 0x00000040);
+ TempVar_a = (UINT16) TempVar_c;
+
+ pPssHeaderAcpiTables->PssLength = (UINT16) TempVar_a;
+ pPssHeaderAcpiTables->NumOfItemsInPss = (UINT8) PstateCount;
+ CurrSize += (PSS_HEADER_STRUCT_SIZE + (PstateCount * PSS_BODY_STRUCT_SIZE));
+
+ *SsdtPtr = pPssBodyAcpiTables;
+ } // end of PSS Body if OptionPstateLateConfiguration.CfgPstatePss
+
+ // Set XPSS Table
+ //---------------
+ // Typecast the pointer
+ pXpssHeaderAcpiTables = (XPSS_HEADER *) pPssBodyAcpiTables;
+ pXpssBodyAcpiTables = (XPSS_BODY *) pPssBodyAcpiTables;
+ if (OptionPstateLateConfiguration.CfgPstateXpss) {
+ // Set XPSS Header
+ // Note: Set the pssLength and numOfItemsInPss later
+ //---------------------------------------------------
+ pXpssHeaderAcpiTables->NameOpcode = NAME_OPCODE;
+ pXpssHeaderAcpiTables->XpssName_a_X = PSS_NAME_X;
+ pXpssHeaderAcpiTables->XpssName_a_P = PSS_NAME_P;
+ pXpssHeaderAcpiTables->XpssName_a_S = PSS_NAME_S;
+ pXpssHeaderAcpiTables->XpssName_b_S = PSS_NAME_S;
+ pXpssHeaderAcpiTables->PkgOpcode = PACKAGE_OPCODE;
+
+ // Increment and then typecast the pointer
+ pXpssHeaderAcpiTables++;
+ pXpssBodyAcpiTables = (XPSS_BODY *) pXpssHeaderAcpiTables;
+ // Restore the pXpssHeaderAcpiTables
+ pXpssHeaderAcpiTables--;
+
+ // Set XPSS Body
+ //---------------
+ for (k = 0; k <= PStateMaxValueOnCurrentCore; k++) {
+ if (PStateLevelingBuffer->PStateCoreStruct[0].PStateStruct[k].PStateEnable != 0) {
+ pXpssBodyAcpiTables->PkgOpcode = PACKAGE_OPCODE;
+ pXpssBodyAcpiTables->PkgLength = XPSS_PKG_LENGTH;
+ pXpssBodyAcpiTables->NumOfElements = XPSS_NUM_OF_ELEMENTS;
+ pXpssBodyAcpiTables->XpssValueTbd = 04;
+ pXpssBodyAcpiTables->DwordPrefixOpcode1 = DWORD_PREFIX_OPCODE;
+ pXpssBodyAcpiTables->Frequency =
+ PStateLevelingBuffer->PStateCoreStruct[0].PStateStruct[k].CoreFreq;
+ pXpssBodyAcpiTables->DwordPrefixOpcode2 = DWORD_PREFIX_OPCODE;
+ pXpssBodyAcpiTables->Power =
+ PStateLevelingBuffer->PStateCoreStruct[0].PStateStruct[k].Power;
+ pXpssBodyAcpiTables->DwordPrefixOpcode3 = DWORD_PREFIX_OPCODE;
+ pXpssBodyAcpiTables->TransitionLatency = TransAndBusMastLatency;
+ pXpssBodyAcpiTables->DwordPrefixOpcode4 = DWORD_PREFIX_OPCODE;
+ pXpssBodyAcpiTables->BusMasterLatency = TransAndBusMastLatency;
+ pXpssBodyAcpiTables->ControlBuffer = XPSS_ACPI_BUFFER;
+ pXpssBodyAcpiTables->ControlLo =
+ PStateLevelingBuffer->PStateCoreStruct[0].PStateStruct[k].SwPstateNumber;
+ pXpssBodyAcpiTables->ControlHi = 0;
+ pXpssBodyAcpiTables->StatusBuffer = XPSS_ACPI_BUFFER;
+ pXpssBodyAcpiTables->StatusLo =
+ PStateLevelingBuffer->PStateCoreStruct[0].PStateStruct[k].SwPstateNumber;
+ pXpssBodyAcpiTables->StatusHi = 0;
+ pXpssBodyAcpiTables->ControlMaskBuffer = XPSS_ACPI_BUFFER;
+ pXpssBodyAcpiTables->ControlMaskLo = 0;
+ pXpssBodyAcpiTables->ControlMaskHi = 0;
+ pXpssBodyAcpiTables->StatusMaskBuffer = XPSS_ACPI_BUFFER;
+ pXpssBodyAcpiTables->StatusMaskLo = 0;
+ pXpssBodyAcpiTables->StatusMaskHi = 0;
+
+ pXpssBodyAcpiTables++;
+ }
+ } // for (k = 0; k < MPPSTATE_MAXIMUM_STATES; k++)
+
+ // Set XPSS Header again
+ // Now set pssLength and numOfItemsInPss
+ //---------------------------------------
+ TempVar_a = (PstateCount * XPSS_BODY_STRUCT_SIZE) + 3;
+ TempVar_b = TempVar_a;
+ TempVar_c = ((TempVar_b << 4) & 0x0000FF00);
+ TempVar_c = TempVar_c | ((TempVar_b & 0x0000000F) | 0x00000040);
+ TempVar_a = (UINT16) TempVar_c;
+
+ pXpssHeaderAcpiTables->XpssLength = (UINT16) TempVar_a;
+ pXpssHeaderAcpiTables->NumOfItemsInXpss = (UINT8) PstateCount;
+ CurrSize += (XPSS_HEADER_STRUCT_SIZE + (PstateCount * XPSS_BODY_STRUCT_SIZE));
+
+ *SsdtPtr = pXpssBodyAcpiTables;
+ } //end of XPSS Body OptionPstateLateConfiguration.CfgPstateXpss
+
+ // Set _PSD Table
+ //---------------
+ // Typecast the pointer
+ pPsdHeaderAcpiTables = (PSD_HEADER *) pXpssBodyAcpiTables;
+ pPsdBodyAcpiTables = (PSD_BODY *) pXpssBodyAcpiTables;
+ // Get Total Cores Per Node
+ if (GetActiveCoresInGivenSocket ((UINT32) PStateLevelingBuffer->SocketNumber, &CoreCount1, StdHeader)) {
+ GetFeatureServicesOfSocket (&PstateFamilyServiceTable, (UINT32) PStateLevelingBuffer->SocketNumber, (CONST VOID **)&FamilyServices, StdHeader);
+ ASSERT (FamilyServices != NULL);
+ if ((CoreCount1 != 1) && (OptionPstateLateConfiguration.CfgPstatePsd) &&
+ FamilyServices->IsPstatePsdNeeded (FamilyServices, PlatformConfig, StdHeader)) {
+ // Set _PSD Header
+ //----------------
+ pPsdHeaderAcpiTables->NameOpcode = NAME_OPCODE;
+ pPsdHeaderAcpiTables->PkgOpcode = PACKAGE_OPCODE;
+ pPsdHeaderAcpiTables->PsdLength = PSD_HEADER_LENGTH;
+ pPsdHeaderAcpiTables->Value1 = PSD_VALUE1;
+ pPsdHeaderAcpiTables->PsdName_a__ = PSD_NAME__;
+ pPsdHeaderAcpiTables->PsdName_a_P = PSD_NAME_P;
+ pPsdHeaderAcpiTables->PsdName_a_S = PSD_NAME_S;
+ pPsdHeaderAcpiTables->PsdName_a_D = PSD_NAME_D;
+
+ // Typecast the pointer
+ pPsdHeaderAcpiTables++;
+ CurrSize += PSD_HEADER_STRUCT_SIZE;
+ pPsdBodyAcpiTables = (PSD_BODY *) pPsdHeaderAcpiTables;
+
+ pPsdHeaderAcpiTables--;
+ // Set _PSD Body
+ //--------------
+ pPsdBodyAcpiTables->PkgOpcode = PACKAGE_OPCODE;
+ pPsdBodyAcpiTables->PkgLength = PSD_PKG_LENGTH;
+ pPsdBodyAcpiTables->NumOfEntries = NUM_OF_ENTRIES;
+ pPsdBodyAcpiTables->BytePrefixOpcode1 = BYTE_PREFIX_OPCODE;
+ pPsdBodyAcpiTables->PsdNumOfEntries = PSD_NUM_OF_ENTRIES;
+ pPsdBodyAcpiTables->BytePrefixOpcode2 = BYTE_PREFIX_OPCODE;
+ pPsdBodyAcpiTables->PsdRevision = PSD_REVISION;
+ pPsdBodyAcpiTables->DwordPrefixOpcode1 = DWORD_PREFIX_OPCODE;
+
+ if (EffectivePstatesPsdPolicy == PsdPolicyProcessorDefault) {
+ IsPsdDependent = FamilyServices->IsPstatePsdDependent (FamilyServices, PlatformConfig, StdHeader);
+ } else {
+ if (EffectivePstatesPsdPolicy == PsdPolicyDependent) {
+ IsPsdDependent = TRUE;
+ } else {
+ IsPsdDependent = FALSE;
+ }
+ IDS_HDT_CONSOLE (CPU_TRACE, " P-state PSD is forced by interface choice as dependent: %d\n", IsPsdDependent);
+ }
+
+ if (IsPsdDependent) {
+ pPsdBodyAcpiTables->DependencyDomain = PSD_DEPENDENCY_DOMAIN;
+ pPsdBodyAcpiTables->CoordinationType = PSD_COORDINATION_TYPE_SW_ALL;
+ pPsdBodyAcpiTables->NumOfProcessors = CoreCount1;
+ } else {
+ switch (GetComputeUnitMapping (StdHeader)) {
+ case AllCoresMapping:
+ // All cores are in their own compute unit.
+ pPsdBodyAcpiTables->DependencyDomain = LocalApicId;
+ pPsdBodyAcpiTables->CoordinationType = PSD_COORDINATION_TYPE_SW_ANY;
+ pPsdBodyAcpiTables->NumOfProcessors = PSD_NUM_OF_PROCESSORS;
+ break;
+ case EvenCoresMapping:
+ // Two cores per compute unit.
+ pPsdBodyAcpiTables->DependencyDomain = LocalApicId >> 1;
+ pPsdBodyAcpiTables->CoordinationType = PSD_COORDINATION_TYPE_HW_ALL;
+ pPsdBodyAcpiTables->NumOfProcessors = PSD_TWO_CORES_PER_COMPUTE_UNIT;
+ break;
+ case TripleCoresMapping:
+ // Three cores per compute unit.
+ pPsdBodyAcpiTables->DependencyDomain = LocalApicId / 3;
+ pPsdBodyAcpiTables->CoordinationType = PSD_COORDINATION_TYPE_HW_ALL;
+ pPsdBodyAcpiTables->NumOfProcessors = PSD_THREE_CORES_PER_COMPUTE_UNIT;
+ break;
+ case QuadCoresMapping:
+ // Four cores per compute unit.
+ pPsdBodyAcpiTables->DependencyDomain = LocalApicId >> 2;
+ pPsdBodyAcpiTables->CoordinationType = PSD_COORDINATION_TYPE_HW_ALL;
+ pPsdBodyAcpiTables->NumOfProcessors = PSD_FOUR_CORES_PER_COMPUTE_UNIT;
+ break;
+ default:
+ ASSERT (FALSE);
+ }
+ }
+ pPsdBodyAcpiTables->DwordPrefixOpcode2 = DWORD_PREFIX_OPCODE;
+ pPsdBodyAcpiTables->DwordPrefixOpcode3 = DWORD_PREFIX_OPCODE;
+
+ pPsdBodyAcpiTables++;
+ *SsdtPtr = pPsdBodyAcpiTables;
+ CurrSize += PSD_BODY_STRUCT_SIZE;
+ }
+ }// end of PSD Body if (CoreCount1 != 1) || (OptionPstateLateConfiguration.CfgPstatePsd)
+ // Typecast the pointer
+
+ pPpcAcpiTables = (PPC_HEADER_BODY *) pPsdBodyAcpiTables;
+
+ // Set _PPC Table
+ //---------------
+ if (OptionPstateLateConfiguration.CfgPstatePpc) {
+ // Name (PPCV, value)
+ pPpcAcpiTables->NameOpcode = NAME_OPCODE;
+ pPpcAcpiTables->PpcName_a_P = PPC_NAME_P;
+ pPpcAcpiTables->PpcName_b_P = PPC_NAME_P;
+ pPpcAcpiTables->PpcName_a_C = PPC_NAME_C;
+ pPpcAcpiTables->PpcName_a_V = PPC_NAME_V;
+ pPpcAcpiTables->Value1 = PPC_VALUE1;
+ pPpcAcpiTables->DefaultPerfPresentCap = PstateCapLevelSupport;
+ // Method (_PPC) { return (PPCV) }
+ pPpcAcpiTables->MethodOpcode = METHOD_OPCODE;
+ pPpcAcpiTables->PpcLength = PPC_METHOD_LENGTH;
+ pPpcAcpiTables->PpcName_a__ = PPC_NAME__;
+ pPpcAcpiTables->PpcName_c_P = PPC_NAME_P;
+ pPpcAcpiTables->PpcName_d_P = PPC_NAME_P;
+ pPpcAcpiTables->PpcName_b_C = PPC_NAME_C;
+ pPpcAcpiTables->MethodFlags = PPC_METHOD_FLAGS;
+ pPpcAcpiTables->ReturnOpcode = RETURN_OPCODE;
+ pPpcAcpiTables->PpcName_e_P = PPC_NAME_P;
+ pPpcAcpiTables->PpcName_f_P = PPC_NAME_P;
+ pPpcAcpiTables->PpcName_c_C = PPC_NAME_C;
+ pPpcAcpiTables->PpcName_b_V = PPC_NAME_V;
+
+ CurrSize += PPC_HEADER_BODY_STRUCT_SIZE;
+ // Increment and typecast the pointer
+ pPpcAcpiTables++;
+ *SsdtPtr = pPpcAcpiTables;
+ }// end of OptionPstateLateConfiguration.CfgPstatePpc
+ }
+ return CurrSize;
+}
+
+/**--------------------------------------------------------------------------------------
+ *
+ * CreateCStateAcpiTables
+ *
+ * Description:
+ * This is the common routine for creating ACPI C-State objects
+ *
+ * Parameters:
+ * @param[in] PlatformConfig Platform operational characteristics; power cap
+ * @param[in] PStateLevelingBuffer Buffer that contains P-State Leveling information
+ * @param[in,out] SsdtPtr ACPI SSDT table pointer
+ * @param[in] LocalApicId Local Apic Id
+ * @param[in] StdHeader Handle to config for library and services
+ *
+ * @retval Size of ACPI C-States objects generated
+ *
+ *---------------------------------------------------------------------------------------
+ **/
+UINT32
+CreateCStateAcpiTables (
+ IN PLATFORM_CONFIGURATION *PlatformConfig,
+ IN PSTATE_LEVELING *PStateLevelingBuffer,
+ IN OUT VOID **SsdtPtr,
+ IN UINT8 LocalApicId,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ UINT32 ObjSize;
+ IO_CSTATE_FAMILY_SERVICES *IoCstateFamilyServices;
+
+ ObjSize = 0;
+
+ if (IsFeatureEnabled (IoCstate, PlatformConfig, StdHeader)) {
+ GetFeatureServicesOfCurrentCore (&IoCstateFamilyServiceTable, (CONST VOID **)&IoCstateFamilyServices, StdHeader);
+ if (IoCstateFamilyServices != NULL) {
+ IoCstateFamilyServices->CreateAcpiCstObj (IoCstateFamilyServices, LocalApicId, SsdtPtr, StdHeader);
+ ObjSize = IoCstateFamilyServices->GetAcpiCstObj (IoCstateFamilyServices, PlatformConfig, StdHeader);
+ }
+ }
+ return ObjSize;
+}
diff --git a/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuPstateTables.h b/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuPstateTables.h
new file mode 100644
index 0000000000..9ccacb4491
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuPstateTables.h
@@ -0,0 +1,314 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * AMD AGESA CPU Pstate Table Functions declarations.
+ *
+ * Contains code that declares the AGESA CPU _PSS related APIs
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: CPU/Feature
+ * @e \$Revision: 84150 $ @e \$Date: 2012-12-12 15:46:25 -0600 (Wed, 12 Dec 2012) $
+ *
+ */
+/*
+ ******************************************************************************
+ *
+ * Copyright (c) 2008 - 2013, Advanced Micro Devices, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Advanced Micro Devices, Inc. nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ ******************************************************************************
+ */
+
+#ifndef _CPU_PSTATE_TABLES_H_
+#define _CPU_PSTATE_TABLES_H_
+
+/*----------------------------------------------------------------------------------------
+ * M I X E D (Definitions And Macros / Typedefs, Structures, Enums)
+ *----------------------------------------------------------------------------------------
+ */
+// Forward declaration needed for multi-structure mutual references
+AGESA_FORWARD_DECLARATION (PSTATE_CPU_FAMILY_SERVICES);
+
+/*----------------------------------------------------------------------------------------
+ * D E F I N I T I O N S A N D M A C R O S
+ *----------------------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------------------
+ * T Y P E D E F S A N D S T R U C T U R E S
+ *----------------------------------------------------------------------------------------
+ */
+/// P-state structure for each state
+typedef struct {
+ IN OUT UINT32 PStateEnable; ///< Pstate enable
+ IN OUT UINT32 CoreFreq; ///< MHz
+ IN OUT UINT32 Power; ///< milliWatts
+ IN OUT UINT32 IddValue; ///< Current value field
+ IN OUT UINT32 IddDiv; ///< Current divisor field
+ IN OUT UINT32 SwPstateNumber; ///< Software P-state number
+} S_PSTATE_VALUES;
+
+/// P-state structure for each core
+typedef struct {
+ IN OUT UINT8 PStateMaxValue; ///< Max p-state number in this core
+ IN OUT UINT8 HtcPstateLimit; ///< Htc limit
+ IN OUT UINT8 HtcCapable; ///< Htc capable
+ IN OUT UINT8 LocalApicId; ///< Local Apic Id
+ IN OUT UINT8 NumberOfBoostedStates; ///< Number of boost P-states
+ IN OUT S_PSTATE_VALUES PStateStruct[1]; ///< P state struc
+} S_PSTATE;
+
+/// P-state structure for each node
+typedef struct {
+ IN UINT8 SetPState0; ///< If value = 0x55 (Don't set PState0)
+ IN UINT8 TotalCoresInNode; ///< core number per node
+ IN UINT16 PStateLevelingSizeOfBytes; ///< Size
+ IN BOOLEAN OnlyOneEnabledPState; ///< Only P0
+ IN UINT8 InitStruct; ///< Init struc
+ IN BOOLEAN AllCpusHaveIdenticalPStates; ///< Have Identical p state
+ IN UINT8 CreateAcpiTables; ///< Create table flag
+ IN UINT8 SocketNumber; ///< Physical socket number of this socket
+ IN UINT8 Reserved[2]; ///< Reserved.
+ IN OUT S_PSTATE PStateCoreStruct[1]; ///< P state core struc
+} PSTATE_LEVELING;
+
+/// P-state structure for whole system
+typedef struct {
+ IN OUT UINT32 TotalSocketInSystem; ///< Total node number in system
+ IN OUT UINT32 SizeOfBytes; ///< Structure size
+ IN OUT PSTATE_LEVELING PStateLevelingStruc[1]; ///< P state level structure
+} S_CPU_AMD_PSTATE;
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * Family specific call to check if PSD need to be generated.
+ *
+ * @param[in] PstateCpuFamilyServices Pstate CPU services.
+ * @param[in,out] PlatformConfig Contains the runtime modifiable feature input data.
+ * @param[in] StdHeader Config Handle for library, services.
+ *
+ * @retval TRUE PSD need to be generated
+ * @retval FALSE PSD does NOT need to be generated
+ *
+ */
+typedef BOOLEAN F_PSTATE_PSD_IS_NEEDED (
+ IN PSTATE_CPU_FAMILY_SERVICES *PstateCpuServices,
+ IN OUT PLATFORM_CONFIGURATION *PlatformConfig,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ );
+
+/// Reference to a Method.
+typedef F_PSTATE_PSD_IS_NEEDED *PF_PSTATE_PSD_IS_NEEDED;
+
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * Family specific call to check if Pstate PSD is dependent.
+ *
+ * @param[in] PstateCpuFamilyServices Pstate CPU services.
+ * @param[in,out] PlatformConfig Contains the runtime modifiable feature input data.
+ * @param[in] StdHeader Config Handle for library, services.
+ *
+ * @retval TRUE PSD is dependent.
+ * @retval FALSE PSD is independent.
+ *
+ */
+typedef BOOLEAN F_PSTATE_PSD_IS_DEPENDENT (
+ IN PSTATE_CPU_FAMILY_SERVICES *PstateCpuServices,
+ IN OUT PLATFORM_CONFIGURATION *PlatformConfig,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ );
+
+/// Reference to a Method.
+typedef F_PSTATE_PSD_IS_DEPENDENT *PF_PSTATE_PSD_IS_DEPENDENT;
+
+/**
+ * Family specific call to get CPU pstate transition latency for current socket.
+ *
+ * @param[in] PstateCpuFamilyServices Pstate CPU services.
+ * @param[in] PStateLevelingBufferStructPtr Pstate row data buffer pointer.
+ * @param[in] PciAddress Pci address struct.
+ * @param[out] TransitionLatency Pstate Transition latency result.
+ * @param[in] StdHeader Handle of Header for calling lib functions and services.
+ *
+ */
+typedef AGESA_STATUS F_CPU_PSTATE_TRANSITION_LATENCY (
+ IN PSTATE_CPU_FAMILY_SERVICES *PstateCpuServices,
+ IN PSTATE_LEVELING *PStateLevelingBufferStructPtr,
+ IN PCI_ADDR *PciAddress,
+ OUT UINT32 *TransitionLatency,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ );
+
+/// Reference to a Method.
+typedef F_CPU_PSTATE_TRANSITION_LATENCY *PF_CPU_PSTATE_TRANSITION_LATENCY;
+
+/**
+ * Family specific call to get the desired P-state's frequency in megahertz.
+ *
+ * @param[in] PstateCpuFamilyServices Pstate CPU services.
+ * @param[in] StateNumber P-state number.
+ * @param[out] PowerInMw P-state frequency in megahertz.
+ * @param[in] StdHeader Handle of Header for calling lib functions and services.
+ *
+ */
+typedef AGESA_STATUS F_CPU_GET_PSTATE_FREQ (
+ IN PSTATE_CPU_FAMILY_SERVICES *PstateCpuServices,
+ IN UINT8 StateNumber,
+ OUT UINT32 *FreqInMHz,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ );
+
+/// Reference to a Method.
+typedef F_CPU_GET_PSTATE_FREQ *PF_CPU_GET_PSTATE_FREQ;
+
+/**
+ * Family specific call to set the system wide P-state settings on the current core.
+ *
+ * @param[in] PstateCpuFamilyServices Pstate CPU services.
+ * @param[in] CpuAmdPState The current core's P-state data.
+ * @param[in] StdHeader Handle of Header for calling lib functions and services.
+ *
+ */
+typedef AGESA_STATUS F_CPU_SET_PSTATE_LEVELING_REG (
+ IN PSTATE_CPU_FAMILY_SERVICES *PstateCpuServices,
+ IN S_CPU_AMD_PSTATE *CpuAmdPState,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ );
+
+/// Reference to a Method.
+typedef F_CPU_SET_PSTATE_LEVELING_REG *PF_CPU_SET_PSTATE_LEVELING_REG;
+
+/**
+ * Family specific call to get the desired P-state's rated power in milliwatts.
+ *
+ * @param[in] PstateCpuFamilyServices Pstate CPU services.
+ * @param[in] StateNumber P-state number.
+ * @param[out] PowerInMw P-state power in milliwatts.
+ * @param[in] StdHeader Handle of Header for calling lib functions and services.
+ *
+ */
+typedef AGESA_STATUS F_CPU_GET_PSTATE_POWER (
+ IN PSTATE_CPU_FAMILY_SERVICES *PstateCpuServices,
+ IN UINT8 StateNumber,
+ OUT UINT32 *PowerInMw,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ );
+
+/// Reference to a Method.
+typedef F_CPU_GET_PSTATE_POWER *PF_CPU_GET_PSTATE_POWER;
+
+/**
+ * Family specific call to get CPU Pstate Max State.
+ *
+ * @param[in] PstateCpuFamilyServices Pstate CPU services.
+ * @param[out] MaxPStateNumber The max hw pstate value on the current socket.
+ * @param[out] NumberOfBoostStates The number of boosted P-states on the current socket.
+ * @param[in] StdHeader Handle of Header for calling lib functions and services.
+ *
+ */
+typedef AGESA_STATUS F_CPU_GET_PSTATE_MAX_STATE (
+ IN PSTATE_CPU_FAMILY_SERVICES *PstateCpuServices,
+ OUT UINT32 *MaxPStateNumber,
+ OUT UINT8 *NumberOfBoostStates,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ );
+
+/// Reference to a Method.
+typedef F_CPU_GET_PSTATE_MAX_STATE *PF_CPU_GET_PSTATE_MAX_STATE;
+
+/**
+ * Family specific call to get CPU pstate register information.
+ *
+ * @param[in] PstateCpuFamilyServices Pstate CPU services.
+ * @param[in] PState Input hardware Pstate number for query.
+ * @param[out] PStateEnabled Boolean flag return pstate enable.
+ * @param[in,out] IddVal Pstate current value.
+ * @param[in,out] IddDiv Pstate current divisor.
+ * @param[out] SwPstateNumber Software P-state number.
+ * @param[in] StdHeader Handle of Header for calling lib functions and services.
+ *
+ */
+typedef AGESA_STATUS F_CPU_GET_PSTATE_REGISTER_INFO (
+ IN PSTATE_CPU_FAMILY_SERVICES *PstateCpuServices,
+ IN UINT32 PState,
+ OUT BOOLEAN *PStateEnabled,
+ IN OUT UINT32 *IddVal,
+ IN OUT UINT32 *IddDiv,
+ OUT UINT32 *SwPstateNumber,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ );
+
+/// Reference to a Method.
+typedef F_CPU_GET_PSTATE_REGISTER_INFO *PF_CPU_GET_PSTATE_REGISTER_INFO;
+
+/**
+ * Provide the interface to the Pstate dependent Family Specific Services.
+ *
+ * Use the methods or data in this struct to adapt the feature code to a specific cpu family or model (or stepping!).
+ * Each supported Family must provide an implementation for all methods in this interface, even if the
+ * implementation is a CommonReturn().
+ */
+struct _PSTATE_CPU_FAMILY_SERVICES {
+ UINT16 Revision; ///< Interface version
+ // Public Methods.
+ PF_PSTATE_PSD_IS_NEEDED IsPstatePsdNeeded; ///< Method: Family specific call to check if PSD need to be generated.
+ PF_PSTATE_PSD_IS_DEPENDENT IsPstatePsdDependent; ///< Method: Family specific call to check if PSD is dependent.
+ PF_CPU_PSTATE_TRANSITION_LATENCY GetPstateLatency; ///< Method: Family specific call to get pstate transition latency.
+ PF_CPU_GET_PSTATE_FREQ GetPstateFrequency; ///< Method: Family specific call to get the desired P-state's frequency in megahertz.
+ PF_CPU_SET_PSTATE_LEVELING_REG SetPStateLevelReg; ///< Method: Family specific call to set the system wide P-state settings on the current core.
+ PF_CPU_GET_PSTATE_POWER GetPstatePower; ///< Method: Family specific call to get the desired P-state's rated power in milliwatts.
+ PF_CPU_GET_PSTATE_MAX_STATE GetPstateMaxState; ///< Method: Family specific call to get pstate max state number.
+ PF_CPU_GET_PSTATE_REGISTER_INFO GetPstateRegisterInfo; ///< Method: Family specific call to get pstate register information.
+};
+
+
+/*----------------------------------------------------------------------------------------
+ * F U N C T I O N S P R O T O T Y P E
+ *----------------------------------------------------------------------------------------
+ */
+AGESA_STATUS
+PStateGatherData (
+ IN PLATFORM_CONFIGURATION *PlatformConfig,
+ IN OUT S_CPU_AMD_PSTATE *PStateStrucPtr,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ );
+
+AGESA_STATUS
+PStateLeveling (
+ IN OUT S_CPU_AMD_PSTATE *PStateStrucPtr,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ );
+
+AGESA_STATUS
+CpuGetPStateLevelStructure (
+ OUT PSTATE_LEVELING **PStateBufferPtr,
+ IN S_CPU_AMD_PSTATE *CpuAmdPState,
+ IN UINT32 LogicalSocketNumber,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ );
+
+#endif // _CPU_PSTATE_TABLES_H_
diff --git a/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuSlit.c b/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuSlit.c
new file mode 100644
index 0000000000..cbabf67287
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuSlit.c
@@ -0,0 +1,398 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * AMD SLIT, ACPI table related API functions.
+ *
+ * Contains code that generates the SLIT table
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: CPU
+ * @e \$Revision: 84150 $ @e \$Date: 2012-12-12 15:46:25 -0600 (Wed, 12 Dec 2012) $
+ *
+ */
+/*
+ ******************************************************************************
+ *
+ * Copyright (c) 2008 - 2013, Advanced Micro Devices, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Advanced Micro Devices, Inc. nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ ******************************************************************************
+ */
+
+/*----------------------------------------------------------------------------
+ * This file provides functions, that will generate SLIT tables
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------------------
+ * M O D U L E S U S E D
+ *----------------------------------------------------------------------------------------
+ */
+
+#include "AGESA.h"
+#include "amdlib.h"
+#include "OptionSlit.h"
+#include "heapManager.h"
+#include "cpuLateInit.h"
+#include "cpuRegisters.h"
+#include "Ids.h"
+#include "cpuFeatures.h"
+#include "cpuFamilyTranslation.h"
+#include "cpuL3Features.h"
+#include "Filecode.h"
+CODE_GROUP (G3_DXE)
+RDATA_GROUP (G3_DXE)
+
+#define FILECODE PROC_CPU_FEATURE_CPUSLIT_FILECODE
+/*----------------------------------------------------------------------------------------
+ * D E F I N I T I O N S A N D M A C R O S
+ *----------------------------------------------------------------------------------------
+ */
+
+extern OPTION_SLIT_CONFIGURATION OptionSlitConfiguration; // global user config record
+
+STATIC ACPI_TABLE_HEADER ROMDATA CpuSlitHdrStruct =
+{
+ {'S','L','I','T'},
+ 0,
+ 1,
+ 0,
+ {0},
+ {0},
+ 1,
+ {'A','M','D',' '},
+ 1
+};
+
+/*----------------------------------------------------------------------------------------
+ * T Y P E D E F S A N D S T R U C T U R E S
+ *----------------------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------------------
+ * P R O T O T Y P E S O F L O C A L F U N C T I O N S
+ *----------------------------------------------------------------------------------------
+ */
+VOID
+STATIC
+AcpiSlitHBufferFind (
+ IN OUT AMD_CONFIG_PARAMS *StdHeader,
+ IN UINT8 **SocketTopologyPtr
+ );
+
+/*----------------------------------------------------------------------------------------
+ * P R O T O T Y P E S O F E X P O R T E D F U N C T I O N S
+ *----------------------------------------------------------------------------------------
+ */
+AGESA_STATUS
+GetAcpiSlitStub (
+ IN OUT AMD_CONFIG_PARAMS *StdHeader,
+ IN PLATFORM_CONFIGURATION *PlatformConfig,
+ IN OUT VOID **SlitPtr
+ );
+
+AGESA_STATUS
+GetAcpiSlitMain (
+ IN OUT AMD_CONFIG_PARAMS *StdHeader,
+ IN PLATFORM_CONFIGURATION *PlatformConfig,
+ IN OUT VOID **SlitPtr
+ );
+
+AGESA_STATUS
+ReleaseSlitBufferStub (
+ IN OUT AMD_CONFIG_PARAMS *StdHeader
+ );
+
+AGESA_STATUS
+ReleaseSlitBuffer (
+ IN OUT AMD_CONFIG_PARAMS *StdHeader
+ );
+
+/*----------------------------------------------------------------------------------------
+ * E X P O R T E D F U N C T I O N S
+ *----------------------------------------------------------------------------------------
+ */
+
+extern CPU_FAMILY_SUPPORT_TABLE L3FeatureFamilyServiceTable;
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ *
+ * This function generates a complete SLIT table into a memory buffer.
+ * After completion, this table must be set by the system BIOS into its
+ * internal ACPI namespace, and linked into the RSDT/XSDT
+ *
+ * @param[in, out] StdHeader Standard Head Pointer
+ * @param[in] PlatformConfig Config handle for platform specific information
+ * @param[in, out] SlitPtr Point to Slit Struct including buffer address and length
+ *
+ * @retval UINT32 AGESA_STATUS
+ */
+AGESA_STATUS
+CreateAcpiSlit (
+ IN OUT AMD_CONFIG_PARAMS *StdHeader,
+ IN PLATFORM_CONFIGURATION *PlatformConfig,
+ IN OUT VOID **SlitPtr
+ )
+{
+ AGESA_TESTPOINT (TpProcCpuEntrySlit, StdHeader);
+ return ((*(OptionSlitConfiguration.SlitFeature)) (StdHeader, PlatformConfig, SlitPtr));
+}
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ *
+ * This is the default routine for use when the SLIT option is NOT requested.
+ *
+ * The option install process will create and fill the transfer vector with
+ * the address of the proper routine (Main or Stub). The link optimizer will
+ * strip out of the .DLL the routine that is not used.
+ *
+ * @param[in, out] StdHeader Standard Head Pointer
+ * @param[in] PlatformConfig Config handle for platform specific information
+ * @param[in, out] SlitPtr Point to Slit Struct including buffer address and length
+ *
+ * @retval AGESA_STATUS
+ */
+
+AGESA_STATUS
+GetAcpiSlitStub (
+ IN OUT AMD_CONFIG_PARAMS *StdHeader,
+ IN PLATFORM_CONFIGURATION *PlatformConfig,
+ IN OUT VOID **SlitPtr
+ )
+{
+ return AGESA_UNSUPPORTED;
+}
+/*---------------------------------------------------------------------------------------*/
+/**
+ *
+ * This function generates a complete SLIT table into a memory buffer.
+ * After completion, this table must be set by the system BIOS into its
+ * internal ACPI namespace, and linked into the RSDT/XSDT
+ *
+ * @param[in, out] StdHeader Standard Head Pointer
+ * @param[in] PlatformConfig Config handle for platform specific information
+ * @param[in, out] SlitPtr Point to Slit Struct including buffer address and length
+ *
+ * @retval UINT32 AGESA_STATUS
+ */
+AGESA_STATUS
+GetAcpiSlitMain (
+ IN OUT AMD_CONFIG_PARAMS *StdHeader,
+ IN PLATFORM_CONFIGURATION *PlatformConfig,
+ IN OUT VOID **SlitPtr
+ )
+{
+ UINT8 MaxHops;
+ UINT8 SocketNum;
+ UINT8 i;
+ UINT8 j;
+ UINT8 *BufferPtr;
+ UINT8 *SocketTopologyDataPtr;
+ UINT8 *SocketTopologyPtr;
+ UINT32 Socket;
+ BOOLEAN var8;
+ ACPI_TABLE_HEADER *CpuSlitHeaderStructPtr;
+ AGESA_STATUS Flag;
+ ALLOCATE_HEAP_PARAMS AllocStruct;
+ L3_FEATURE_FAMILY_SERVICES *FamilyServices;
+
+ MaxHops = 0;
+ SocketTopologyPtr = NULL;
+ Flag = AGESA_ERROR;
+ var8 = FALSE;
+
+ // find out the pointer to the BufferHandle which contains
+ // Node Topology information
+ AcpiSlitHBufferFind (StdHeader, &SocketTopologyPtr);
+ if (SocketTopologyPtr == NULL) {
+ return (Flag);
+ }
+
+ SocketNum = *SocketTopologyPtr;
+
+ IDS_HDT_CONSOLE (CPU_TRACE, " SLIT is created\n");
+
+ // create a buffer by calling IBV callout routine
+ AllocStruct.RequestedBufferSize = (SocketNum * SocketNum) + AMD_ACPI_SLIT_SOCKET_NUM_LENGTH + sizeof (ACPI_TABLE_HEADER);
+ AllocStruct.BufferHandle = AMD_ACPI_SLIT_BUFFER_HANDLE;
+ AllocStruct.Persist = HEAP_SYSTEM_MEM;
+ if (HeapAllocateBuffer (&AllocStruct, StdHeader) != AGESA_SUCCESS) {
+ return (Flag);
+ }
+ *SlitPtr = AllocStruct.BufferPtr;
+
+ //SLIT header
+ LibAmdMemCopy (*SlitPtr, (VOID *) &CpuSlitHdrStruct, (UINTN) (sizeof (ACPI_TABLE_HEADER)), StdHeader);
+ CpuSlitHeaderStructPtr = (ACPI_TABLE_HEADER *) *SlitPtr;
+ CpuSlitHeaderStructPtr->TableLength = (UINT32) AllocStruct.RequestedBufferSize;
+ // Update table OEM fields.
+ LibAmdMemCopy ((VOID *) &CpuSlitHeaderStructPtr->OemId, (VOID *) &OptionSlitConfiguration.OemIdString,
+ sizeof (OptionSlitConfiguration.OemIdString), StdHeader);
+ LibAmdMemCopy ((VOID *) &CpuSlitHeaderStructPtr->OemTableId, (VOID *) &OptionSlitConfiguration.OemTableIdString,
+ sizeof (OptionSlitConfiguration.OemTableIdString), StdHeader);
+ BufferPtr = *SlitPtr;
+
+ Flag = AGESA_SUCCESS;
+ // SLIT body
+ if (IsFeatureEnabled (L3Features, PlatformConfig, StdHeader)) {
+ var8 = TRUE;
+ for (Socket = 0; Socket < GetPlatformNumberOfSockets (); Socket++) {
+ if (IsProcessorPresent (Socket, StdHeader)) {
+ GetFeatureServicesOfSocket (&L3FeatureFamilyServiceTable, Socket, (CONST VOID **)&FamilyServices, StdHeader);
+ if ((FamilyServices == NULL) || (!FamilyServices->IsHtAssistSupported (FamilyServices, PlatformConfig, StdHeader))) {
+ var8 = FALSE;
+ break;
+ }
+ }
+ }
+ }
+
+
+ if (!var8) {
+ // get MaxHops
+ SocketTopologyDataPtr = SocketTopologyPtr + sizeof (SocketNum);
+ for (i = 0; i < SocketNum; i++) {
+ for (j = 0; j < SocketNum; j++) {
+ if (*SocketTopologyDataPtr > MaxHops) {
+ MaxHops = *SocketTopologyDataPtr;
+ }
+ SocketTopologyDataPtr++;
+ }
+ }
+
+ // the Max hop entries have a value of 13
+ // and all other entries have 10.
+ SocketTopologyDataPtr = SocketTopologyPtr + sizeof (SocketNum);
+ for (i = 0; i < SocketNum; i++) {
+ for (j = 0; j < SocketNum; j++) {
+ if (*SocketTopologyDataPtr++ == MaxHops) {
+ *(BufferPtr + sizeof (ACPI_TABLE_HEADER) +
+ AMD_ACPI_SLIT_SOCKET_NUM_LENGTH + (i * SocketNum) + j) = 13;
+ } else {
+ *(BufferPtr + sizeof (ACPI_TABLE_HEADER) +
+ AMD_ACPI_SLIT_SOCKET_NUM_LENGTH + (i * SocketNum) + j) = 10;
+ }
+ }
+ }
+ } else {
+ // formula : num_hops * 6 + 10
+ SocketTopologyDataPtr = SocketTopologyPtr + sizeof (SocketNum);
+ for (i = 0; i < SocketNum; i++) {
+ for (j = 0; j < SocketNum; j++) {
+ *(BufferPtr + sizeof (ACPI_TABLE_HEADER) +
+ AMD_ACPI_SLIT_SOCKET_NUM_LENGTH + (i * SocketNum) + j) =
+ ((*SocketTopologyDataPtr++) * 6) + 10;
+ }
+ }
+ }
+
+ BufferPtr += sizeof (ACPI_TABLE_HEADER);
+ *((UINT64 *) BufferPtr) = (UINT64) SocketNum;
+
+ //Update SLIT header Checksum
+ ChecksumAcpiTable ((ACPI_TABLE_HEADER *) *SlitPtr, StdHeader);
+
+ return (Flag);
+}
+
+/*---------------------------------------------------------------------------------------
+ * L O C A L F U N C T I O N S
+ *---------------------------------------------------------------------------------------
+ */
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ *
+ * Find out the pointer to the BufferHandle which contains
+ * Node Topology information
+ *
+ * @param[in, out] StdHeader Standard Head Pointer
+ * @param[in] SocketTopologyPtr Point to the address of Socket Topology
+ *
+ */
+VOID
+STATIC
+AcpiSlitHBufferFind (
+ IN OUT AMD_CONFIG_PARAMS *StdHeader,
+ IN UINT8 **SocketTopologyPtr
+ )
+{
+ LOCATE_HEAP_PTR LocateBuffer;
+
+ LocateBuffer.BufferHandle = HOP_COUNT_TABLE_HANDLE;
+ if (HeapLocateBuffer (&LocateBuffer, StdHeader) == AGESA_SUCCESS) {
+ *SocketTopologyPtr = (UINT8 *) LocateBuffer.BufferPtr;
+ }
+
+ return;
+}
+
+
+/* -----------------------------------------------------------------------------*/
+/**
+ * ReleaseSlitBufferStub
+ *
+ * Description:
+ * This is the default routine for use when the SLIT option is NOT requested.
+ *
+ * Parameters:
+ * @param[in, out] *StdHeader
+ *
+ * @retval AGESA_STATUS
+ *
+ */
+AGESA_STATUS
+ReleaseSlitBufferStub (
+ IN OUT AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ return AGESA_UNSUPPORTED;
+}
+
+/* -----------------------------------------------------------------------------*/
+/**
+ * ReleaseSlitBuffer
+ *
+ * Description:
+ * Deallocate SLIT buffer
+ *
+ * Parameters:
+ * @param[in, out] *StdHeader
+ *
+ * @retval AGESA_STATUS
+ *
+ */
+AGESA_STATUS
+ReleaseSlitBuffer (
+ IN OUT AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ HeapDeallocateBuffer ((UINT32) HOP_COUNT_TABLE_HANDLE, StdHeader);
+
+ return AGESA_SUCCESS;
+}
diff --git a/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuSrat.c b/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuSrat.c
new file mode 100644
index 0000000000..9d6ca3d06b
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuSrat.c
@@ -0,0 +1,618 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * AMD SRAT, ACPI table related API functions.
+ *
+ * Contains code that Create the APCI SRAT Table after early reset.
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: CPU
+ * @e \$Revision: 84150 $ @e \$Date: 2012-12-12 15:46:25 -0600 (Wed, 12 Dec 2012) $
+ *
+ */
+/*
+ ******************************************************************************
+ *
+ * Copyright (c) 2008 - 2013, Advanced Micro Devices, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Advanced Micro Devices, Inc. nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ ***************************************************************************/
+
+
+/*----------------------------------------------------------------------------
+ * This file provides functions, that will generate SRAT tables
+ *----------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------------------
+ * M O D U L E S U S E D
+ *----------------------------------------------------------------------------------------
+ */
+#include "AGESA.h"
+#include "amdlib.h"
+#include "cpuServices.h"
+#include "OptionSrat.h"
+#include "heapManager.h"
+#include "cpuRegisters.h"
+#include "cpuLateInit.h"
+#include "Ids.h"
+#include "Filecode.h"
+CODE_GROUP (G3_DXE)
+RDATA_GROUP (G3_DXE)
+
+#define FILECODE PROC_CPU_FEATURE_CPUSRAT_FILECODE
+/*----------------------------------------------------------------------------------------
+ * D E F I N I T I O N S A N D M A C R O S
+ *----------------------------------------------------------------------------------------
+ */
+extern OPTION_SRAT_CONFIGURATION OptionSratConfiguration; // global user config record
+
+#define NodeID 0x60
+#define FOURGB 0x010000ul
+
+/*----------------------------------------------------------------------------------------
+ * T Y P E D E F S A N D S T R U C T U R E S
+ *----------------------------------------------------------------------------------------
+ */
+AGESA_STATUS
+GetAcpiSratStub (
+ IN OUT AMD_CONFIG_PARAMS *StdHeader,
+ IN OUT VOID **SratPtr
+ );
+
+AGESA_STATUS
+GetAcpiSratMain (
+ IN OUT AMD_CONFIG_PARAMS *StdHeader,
+ IN OUT VOID **SratPtr
+ );
+
+/*----------------------------------------------------------------------------
+ * All of the DATA should be defined in _CODE segment.
+ * Use ROMDATA to specify that it belongs to _CODE.
+ *----------------------------------------------------------------------------
+ */
+STATIC CPU_SRAT_HEADER ROMDATA CpuSratHdrStruct =
+{
+ {'S','R','A','T'},
+ 0,
+ 2,
+ 0,
+ {0},
+ {0},
+ 1,
+ {'A','M','D',' '},
+ 1,
+ 1,
+ {0, 0, 0, 0, 0, 0, 0, 0}
+};
+
+/*----------------------------------------------------------------------------------------
+ * P R O T O T Y P E S O F L O C A L F U N C T I O N S
+ *----------------------------------------------------------------------------------------
+ */
+UINT8
+STATIC
+*MakeApicEntry (
+ IN UINT8 ApicId,
+ IN UINT8 Domain,
+ IN UINT8 *BufferLocPtr
+ );
+
+UINT8
+STATIC
+*FillMemoryForCurrentNode (
+ IN UINT8 *PDomain,
+ IN OUT UINT8 *PDomainForBase640K,
+ IN UINT8 Node,
+ IN OUT UINT8 *BufferLocPtr,
+ IN OUT AMD_CONFIG_PARAMS *StdHeader
+ );
+
+UINT8
+STATIC
+*MakeMemEntry (
+ IN UINT8 PDomain,
+ IN UINT8 Node,
+ IN UINT32 Base,
+ IN UINT32 Size,
+ IN UINT8 *BufferLocPtr
+ );
+
+/*----------------------------------------------------------------------------------------
+ * E X P O R T E D F U N C T I O N S
+ *----------------------------------------------------------------------------------------
+ */
+/*---------------------------------------------------------------------------------------*/
+/**
+ *
+ * This function will generate a complete Static Resource Affinity Table
+ * i.e. SRAT into a memory buffer. After completion, this table must be set
+ * by the system BIOS into its internal ACPI name space.
+ *
+ * @param[in, out] StdHeader Standard Head Pointer
+ * @param[in, out] SratPtr Point to Srat Struct including buffer address and length
+ *
+ * @retval AGESA_STATUS
+ */
+
+AGESA_STATUS
+CreateAcpiSrat (
+ IN OUT AMD_CONFIG_PARAMS *StdHeader,
+ IN OUT VOID **SratPtr
+ )
+{
+ AGESA_TESTPOINT (TpProcCpuEntrySrat, StdHeader);
+ return ((*(OptionSratConfiguration.SratFeature)) (StdHeader, SratPtr));
+}
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ *
+ * This is the default routine for use when the SRAT option is NOT requested.
+ *
+ * The option install process will create and fill the transfer vector with
+ * the address of the proper routine (Main or Stub). The link optimizer will
+ * strip out of the .DLL the routine that is not used.
+ *
+ * @param[in, out] StdHeader Standard Head Pointer
+ * @param[in, out] SratPtr Point to Srat Struct including buffer address and length
+ *
+ * @retval AGESA_STATUS
+ */
+
+AGESA_STATUS
+GetAcpiSratStub (
+ IN OUT AMD_CONFIG_PARAMS *StdHeader,
+ IN OUT VOID **SratPtr
+ )
+{
+ return AGESA_UNSUPPORTED;
+}
+/*---------------------------------------------------------------------------------------*/
+/**
+ *
+ * This function will generate a complete Static Resource Affinity Table
+ * i.e. SRAT into a memory buffer. After completion, this table must be set
+ * by the system BIOS into its internal ACPI name space.
+ *
+ * @param[in, out] StdHeader Standard Head Pointer
+ * @param[in, out] SratPtr Point to Srat Struct including buffer address and length
+ *
+ * @retval AGESA_STATUS
+ */
+AGESA_STATUS
+GetAcpiSratMain (
+ IN OUT AMD_CONFIG_PARAMS *StdHeader,
+ IN OUT VOID **SratPtr
+ )
+{
+ UINT8 *BufferPtr;
+ UINT8 NodeNum;
+ UINT8 NodeCount;
+ UINT8 PDomain;
+ UINT8 PDomainForBase640K;
+ UINT32 Socket;
+ UINT32 Module;
+ UINT32 LowCore;
+ UINT32 HighCore;
+ UINT32 CoreNum;
+ UINT32 tempVar_32;
+ AMD_APIC_PARAMS ApicParams;
+ CPU_SRAT_HEADER *CpuSratHeaderStructPtr;
+ ALLOCATE_HEAP_PARAMS AllocParams;
+
+ // Get Node count
+ NodeCount = 1;
+ NodeCount = 1;
+
+ // The worst-case buffer size to request is for the SRAT table header, one
+ // entree for special region (base 640k block), two memory
+ // regions per node, and APIC entries for each core in the system.
+ tempVar_32 = (sizeof (CPU_SRAT_HEADER)) + (sizeof (CPU_SRAT_MEMORY_ENTRY))
+ + ((UINT32) NodeCount * (2 * (sizeof (CPU_SRAT_MEMORY_ENTRY))
+ + ((UINT32) GetActiveCoresInCurrentModule (StdHeader) * sizeof (CPU_SRAT_APIC_ENTRY))));
+
+ if (*SratPtr == NULL) {
+ //
+ // Allocate a buffer
+ //
+ AllocParams.RequestedBufferSize = tempVar_32;
+ AllocParams.BufferHandle = AMD_SRAT_INFO_BUFFER_HANDLE;
+ AllocParams.Persist = HEAP_SYSTEM_MEM;
+
+ AGESA_TESTPOINT (TpProcCpuBeforeAllocateSratBuffer, StdHeader);
+ if (HeapAllocateBuffer (&AllocParams, StdHeader) != AGESA_SUCCESS) {
+ return AGESA_ERROR;
+ }
+ AGESA_TESTPOINT (TpProcCpuAfterAllocateSratBuffer, StdHeader);
+
+ *SratPtr = AllocParams.BufferPtr;
+ }
+
+ IDS_HDT_CONSOLE (CPU_TRACE, " SRAT is created\n");
+
+ CpuSratHeaderStructPtr = (CPU_SRAT_HEADER *) *SratPtr;
+ BufferPtr = (UINT8 *) *SratPtr;
+
+ // Copy acpiSRATHeader -> data buffer
+ LibAmdMemCopy (*SratPtr, (VOID *) &CpuSratHdrStruct, (UINTN) (sizeof (CPU_SRAT_HEADER)), StdHeader);
+ // Update table OEM fields.
+ LibAmdMemCopy ((VOID *) &CpuSratHeaderStructPtr->OemId, (VOID *) &OptionSratConfiguration.OemIdString,
+ sizeof (OptionSratConfiguration.OemIdString), StdHeader);
+ LibAmdMemCopy ((VOID *) &CpuSratHeaderStructPtr->OemTableId, (VOID *) &OptionSratConfiguration.OemTableIdString,
+ sizeof (OptionSratConfiguration.OemTableIdString), StdHeader);
+
+ BufferPtr += sizeof (CPU_SRAT_HEADER);
+
+ // Place all memory and IO affinity entries
+ NodeNum = 0;
+ PDomain = 0;
+ PDomainForBase640K = 0xFF;
+ ApicParams.StdHeader = *StdHeader;
+ while (NodeNum < NodeCount) {
+ GetSocketModuleOfNode ((UINT32) NodeNum, &Socket, &Module, StdHeader);
+ GetGivenModuleCoreRange (Socket, Module, &LowCore, &HighCore, StdHeader);
+ BufferPtr = FillMemoryForCurrentNode (&PDomain, &PDomainForBase640K, NodeNum, BufferPtr, StdHeader);
+ for (CoreNum = LowCore; CoreNum <= HighCore; CoreNum++) {
+ ApicParams.Socket = (UINT8) Socket;
+ ApicParams.Core = (UINT8) CoreNum;
+ AmdGetApicId (&ApicParams);
+ if (ApicParams.IsPresent) {
+ BufferPtr = MakeApicEntry (ApicParams.ApicAddress, PDomain, BufferPtr);
+ }
+ }
+
+ NodeNum++;
+ PDomain = NodeNum;
+ }
+
+ // Store size in table (current buffer offset - buffer start offset)
+ CpuSratHeaderStructPtr->TableLength = (UINT32) (BufferPtr - (UINT8 *) CpuSratHeaderStructPtr);
+
+ //Update SSDT header Checksum
+ ChecksumAcpiTable ((ACPI_TABLE_HEADER *) CpuSratHeaderStructPtr, StdHeader);
+
+ return AGESA_SUCCESS;
+}
+
+
+/*----------------------------------------------------------------------------------------
+ * L O C A L F U N C T I O N S
+ *----------------------------------------------------------------------------------------
+ */
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ *
+ * This function will build Memory entry for current node.
+ * Note that we only create a memory affinity entry if we find one
+ * that matches the current node. This makes an easier to read table
+ * though it is not necessary.
+ *
+ * @param[in] PDomain Proximity Domain
+ * @param[in, out] PDomainForBase640K The PDomain for Base 640K
+ * @param[in] Node The number of Node
+ * @param[in, out] BufferLocPtr Point to the address of buffer
+ * @param[in, out] StdHeader Standard Head Pointer
+ *
+ * @retval UINT8 *(New buffer location ptr)
+ */
+UINT8
+STATIC
+*FillMemoryForCurrentNode (
+ IN UINT8 *PDomain,
+ IN OUT UINT8 *PDomainForBase640K,
+ IN UINT8 Node,
+ IN OUT UINT8 *BufferLocPtr,
+ IN OUT AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ UINT32 ValueLimit;
+ UINT32 ValueTOM;
+ BOOLEAN isModified;
+ UINT8 Domain;
+ UINT32 RegVal;
+ UINT32 DramLeng;
+ UINT32 DramBase;
+ UINT32 DramLimit;
+ UINT32 OffsetRegs;
+ PCI_ADDR PciAddress;
+ UINT64 MsrValue;
+ UINT32 TopOfMemoryAbove4Gb;
+
+ Domain = *PDomain;
+
+ PciAddress.Address.Segment = 0;
+ PciAddress.Address.Bus = 0;
+ PciAddress.Address.Device = LOW_NODE_DEVICEID;
+ PciAddress.Address.Function = FUNC_1;
+
+ for (OffsetRegs = DRAMBase0; OffsetRegs < MMIOBase0; OffsetRegs += 8) {
+ isModified = FALSE; // FALSE means normal update procedure
+ // Get DRAM Base Address
+ PciAddress.Address.Register = OffsetRegs;
+ LibAmdPciRead (AccessWidth32, PciAddress, &DramBase, StdHeader);
+ if ((DramBase & 3) != 3) {
+ // 0:1 set if memory range enabled
+ // Not set, so we don't have an enabled range
+ continue; // Proceed to next Base register
+ }
+
+ // Get DRAM Limit
+ PciAddress.Address.Register = OffsetRegs + 4;
+ LibAmdPciRead (AccessWidth32, PciAddress, &DramLimit, StdHeader);
+ if (DramLimit == 0xFFFFFFFF) {
+ // Node not installed(all FF's)?
+ continue; // Proceed to next Base register
+ }
+
+ if ((DramLimit & 0xFF) != Node) {
+ // Check if Destination Node ID is current node
+ continue; // Proceed to next Base register
+ }
+
+ // We only add an entry now if detected range belongs to current node/PDomain
+ PciAddress.Address.Register = OffsetRegs + 0x104;
+ LibAmdPciRead (AccessWidth32, PciAddress, &RegVal, StdHeader);
+
+ DramLimit = (((RegVal & 0xFF) << 16) | (DramLimit >> 16)); // Get DRAM Limit addr [47:24]
+ DramLimit++; // Add 1 for potential length
+ DramLimit <<= 8;
+
+ // Get DRAM Base Address
+ PciAddress.Address.Register = OffsetRegs + 0x100;
+ LibAmdPciRead (AccessWidth32, PciAddress, &RegVal, StdHeader);
+ DramBase = ((((RegVal & 0xFF) << 24) | (DramBase >> 8)) & 0xFFFFFF00); // Get DRAM Base Base value [47:24]
+ DramLeng = DramLimit - DramBase; // Subtract base from limit to get length
+
+ // Leave hole for conventional memory (Less than 640K). It must be on CPU 0.
+ if (DramBase == 0) {
+ if (*PDomainForBase640K == 0xFF) {
+ // It is the first time that the range start at 0.
+ // If Yes, then Place 1MB memory gap and save Domain to PDomainForBase640K
+ BufferLocPtr = MakeMemEntry (
+ Domain,
+ Node,
+ 0, // Base = 0
+ 0xA0000 >> 16, // Put it into format used in DRAM regs..
+ BufferLocPtr
+ );
+ DramBase += 0x10; // Add 1MB, so range = 1MB to Top of Region
+ DramLeng -= 0x10; // Also subtract 1MB from the length
+ *PDomainForBase640K = Domain; // Save Domain number for memory Less than 640K
+ } else {
+ // If No, there are more than one memory range less than 640K, it should that
+ // node interleaving is enabled. All nodes have the same memory ranges
+ // and all cores in these nodes belong to the same domain.
+ *PDomain = *PDomainForBase640K;
+ return (BufferLocPtr);
+ }
+ }
+ LibAmdMsrRead (TOP_MEM, &MsrValue, StdHeader);
+ ValueTOM = (UINT32) MsrValue >> 16; // Save it in 39:24 format
+ ValueLimit = DramBase + DramLeng; // We need to know how large region is
+
+ LibAmdMsrRead (SYS_CFG, &MsrValue, StdHeader);
+ if ((MsrValue & BIT21) != 0) {
+ LibAmdMsrRead (TOP_MEM2, &MsrValue, StdHeader);
+ TopOfMemoryAbove4Gb = (UINT32) (MsrValue >> 16); // Save it in 47:16 format
+ } else {
+ TopOfMemoryAbove4Gb = 0xFFFFFFFF;
+ }
+
+ // SPECIAL CASES:
+ //
+ // Several conditions require that we process the values of the memory range differently.
+ // Here are descriptions of the corner cases.
+ //
+ // 1. TRUNCATE LOW - Memory range starts below TOM, ends in TOM (memory hole). For this case,
+ // the range must be truncated to end at TOM.
+ // ******************************* *******************************
+ // * * * -> * *
+ // ******************************* *******************************
+ // 2 TOM 4 2 TOM
+ //
+ // 2. TRUNCATE HIGH - Memory range starts below 4GB, ends above 4GB. This is handled by changing the
+ // start base to 4GB.
+ // **************** **********
+ // * * * -> * *
+ // **************** **********
+ // TOM 3.8 4 6 TOM 3.8 4 6
+ //
+ // 3. Memory range starts below TOM, ends above 4GB. For this case, the range must be truncated
+ // to end at TOM. Note that this scenario creates two ranges, as the second comparison below
+ // will find that it ends above 4GB since base and limit have been restored after first truncation,
+ // and a second range will be written based at 4GB ending at original end address.
+ // ******************************* **************** **********
+ // * * * * -> * * * *
+ // ******************************* **************** **********
+ // 2 TOM 4 6 2 TOM 4 6
+ //
+ // 4. Memory range starts above TOM, ends below or equal to 4GB. This invalid range should simply
+ // be ignored.
+ // *******
+ // * * -> < NULL >
+ // *******
+ // TOM 3.8 4
+ //
+ // 5. Memory range starts below TOM2, and ends beyond TOM2. This range must be truncated to TOM2.
+ // ************************ *******************************
+ // * * * -> * *
+ // ************************ *******************************
+ // 768 TOM2 1024 768 TOM2
+ //
+ // 6. Memory range starts above TOM2. This invalid range should simply be ignored.
+ // ********************
+ // * * -> < NULL >
+ // ********************
+ // TOM2 1024 1280
+
+ if (((DramBase < ValueTOM) && (ValueLimit <= FOURGB) && (ValueLimit > ValueTOM))
+ || ((DramBase < ValueTOM) && (ValueLimit > FOURGB))) {
+ // TRUNCATE LOW!!! Shrink entry below TOM...
+ // Base = DramBase, Size = TOM - DramBase
+ BufferLocPtr = MakeMemEntry (Domain, Node, DramBase, (ValueTOM - DramBase), BufferLocPtr);
+ isModified = TRUE;
+ }
+
+ if ((ValueLimit > FOURGB) && (DramBase < FOURGB)) {
+ // TRUNCATE HIGH!!! Shrink entry above 4GB...
+ // Size = Base + Size - 4GB, Base = 4GB
+ BufferLocPtr = MakeMemEntry (Domain, Node, FOURGB, (DramLeng + DramBase - FOURGB), BufferLocPtr);
+ isModified = TRUE;
+ }
+
+ if ((DramBase >= ValueTOM) && (ValueLimit <= FOURGB)) {
+ // IGNORE!!! Entry located entirely within memory hole
+ isModified = TRUE;
+ }
+
+ if ((DramBase < TopOfMemoryAbove4Gb) && (ValueLimit > TopOfMemoryAbove4Gb)) {
+ // Truncate to TOM2
+ // Base = DramBase, Size = TOM2 - DramBase
+ BufferLocPtr = MakeMemEntry (Domain, Node, DramBase, (TopOfMemoryAbove4Gb - DramBase), BufferLocPtr);
+ isModified = TRUE;
+ }
+
+ if (DramBase >= TopOfMemoryAbove4Gb) {
+ // IGNORE!!! Entry located entirely above TOM2
+ isModified = TRUE;
+ }
+
+ // If special range(isModified), we are done.
+ // If not, finally write the memory entry.
+ if (isModified == FALSE) {
+ // Finally write the memory entry.
+ BufferLocPtr = MakeMemEntry (Domain, Node, DramBase, DramLeng, BufferLocPtr);
+ }
+
+ } // for ( OffsetRegs = DRAMBase0; ... )
+
+ return (BufferLocPtr);
+} // FillMemoryForCurrentNode()
+
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * This function will add APIC entry.
+ *
+ * @param[in] ApicId APIC ID number
+ * @param[in] Domain Domain number
+ * @param[in] BufferLocPtr Point to the address of buffer
+ *
+ * @retval UINT8 *(New buffer location ptr)
+ */
+UINT8
+STATIC
+*MakeApicEntry (
+ IN UINT8 ApicId,
+ IN UINT8 Domain,
+ IN UINT8 *BufferLocPtr
+ )
+{
+ CPU_SRAT_APIC_ENTRY *psSratApicEntry;
+ UINT8 ReservedBytes;
+
+ psSratApicEntry = (CPU_SRAT_APIC_ENTRY *)BufferLocPtr;
+
+ psSratApicEntry->Type = AE_APIC;
+ psSratApicEntry->Length = (UINT8)sizeof (CPU_SRAT_APIC_ENTRY);
+ psSratApicEntry->Domain = Domain;
+ psSratApicEntry->ApicId = ApicId;
+ psSratApicEntry->Flags = ENABLED;
+ psSratApicEntry->LSApicEid = 0;
+ for (ReservedBytes = 0; ReservedBytes < (UINT8)sizeof (psSratApicEntry->Reserved); ReservedBytes++) {
+ psSratApicEntry->Reserved[ReservedBytes] = 0;
+ }
+ return (BufferLocPtr + (UINT8)sizeof (CPU_SRAT_APIC_ENTRY));
+} // MakeApicEntry
+
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ *
+ * This function will add Memory entry.
+ *
+ * Parameters:
+ * @param[in] PDomain Proximity Domain
+ * @param[in] Node The number of Node
+ * @param[in] Base Memory Base
+ * @param[in] Size Memory Size
+ * @param[in] BufferLocPtr Point to the address of buffer
+ *
+ * @retval UINT8 * (new buffer location ptr)
+ */
+UINT8
+STATIC
+*MakeMemEntry (
+ IN UINT8 PDomain,
+ IN UINT8 Node,
+ IN UINT32 Base,
+ IN UINT32 Size,
+ IN UINT8 *BufferLocPtr
+ )
+{
+ CPU_SRAT_MEMORY_ENTRY *psSratMemEntry;
+ UINT8 ReservedBytes;
+
+ psSratMemEntry = (CPU_SRAT_MEMORY_ENTRY *)BufferLocPtr;
+
+ psSratMemEntry->Type = AE_MEMORY; // [0] = Memory Entry
+ psSratMemEntry->Length = (UINT8)sizeof (CPU_SRAT_MEMORY_ENTRY); // [1] = 40
+ psSratMemEntry->Domain = PDomain; // [2] = Proximity Domain
+
+ // [6-7] = Reserved
+ for (ReservedBytes = 0; ReservedBytes < (UINT8)sizeof (psSratMemEntry->Reserved1); ReservedBytes++) {
+ psSratMemEntry->Reserved1[ReservedBytes] = 0;
+ }
+
+ // [8-11] = Keep 31:0 of address only -> Base Addr Low
+ psSratMemEntry->BaseAddrLow = Base << 16;
+
+ // [12-15] = Keep 39:32 of address only -> Base Addr High
+ psSratMemEntry->BaseAddrHigh = Base >> 16;
+
+ // [16-19] = Keep 31:0 of address only -> Length Low
+ psSratMemEntry->LengthAddrLow = Size << 16;
+
+ // [20-23] = Keep 39:32 of address only -> Length High
+ psSratMemEntry->LengthAddrHigh = Size >> 16;
+
+ // [24-27] = Reserved
+ for (ReservedBytes = 0; ReservedBytes < (UINT8)sizeof (psSratMemEntry->Reserved2); ReservedBytes++) {
+ psSratMemEntry->Reserved2[ReservedBytes] = 0;
+ }
+
+ // [28-31] = Flags
+ psSratMemEntry->Flags = ENABLED;
+
+ // [32-40] = Reserved
+ for (ReservedBytes = 0; ReservedBytes < (UINT8)sizeof (psSratMemEntry->Reserved3); ReservedBytes++) {
+ psSratMemEntry->Reserved3[ReservedBytes] = 0;
+ }
+ return (BufferLocPtr + (UINT8)sizeof (CPU_SRAT_MEMORY_ENTRY));
+} // MakeMemEntry()
+
diff --git a/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuTdpLimiting.h b/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuTdpLimiting.h
new file mode 100644
index 0000000000..91ccd33790
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuTdpLimiting.h
@@ -0,0 +1,129 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * AMD AGESA CPU TDP limiting Functions declarations.
+ *
+ * Contains code that declares the AGESA CPU TDP limiting related APIs
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: CPU/Feature
+ * @e \$Revision: 84150 $ @e \$Date: 2012-12-12 15:46:25 -0600 (Wed, 12 Dec 2012) $
+ *
+ */
+/*
+ ******************************************************************************
+ *
+ * Copyright (c) 2008 - 2013, Advanced Micro Devices, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Advanced Micro Devices, Inc. nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ ******************************************************************************
+ */
+
+#ifndef _CPU_TDP_LIMITING_H_
+#define _CPU_TDP_LIMITING_H_
+
+/*----------------------------------------------------------------------------------------
+ * M I X E D (Definitions And Macros / Typedefs, Structures, Enums)
+ *----------------------------------------------------------------------------------------
+ */
+// Forward declaration needed for multi-structure mutual references
+AGESA_FORWARD_DECLARATION (TDP_LIMIT_FAMILY_SERVICES);
+
+/*----------------------------------------------------------------------------------------
+ * D E F I N I T I O N S A N D M A C R O S
+ *----------------------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------------------
+ * T Y P E D E F S A N D S T R U C T U R E S
+ *----------------------------------------------------------------------------------------
+ */
+
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * Family specific call to check if TDP limiting is supported.
+ *
+ * @param[in] TdpLimitServices TDP limiting services.
+ * @param[in] PlatformConfig Contains the runtime modifiable feature input data.
+ * @param[in] Socket Zero-based socket number.
+ * @param[in] StdHeader Config Handle for library, services.
+ *
+ * @retval TRUE TDP limiting is supported.
+ * @retval FALSE TDP limiting is not supported.
+ *
+ */
+typedef BOOLEAN F_TDP_LIMIT_IS_SUPPORTED (
+ IN TDP_LIMIT_FAMILY_SERVICES *TdpLimitServices,
+ IN PLATFORM_CONFIGURATION *PlatformConfig,
+ IN UINT32 Socket,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ );
+
+/// Reference to a Method.
+typedef F_TDP_LIMIT_IS_SUPPORTED *PF_TDP_LIMIT_IS_SUPPORTED;
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * Family specific call to enable TDP limiting.
+ *
+ * @param[in] TdpLimitServices TDP limiting services.
+ * @param[in] PowerCeiling Specifies a maximum power usage limit for the platform.
+ * @param[in] StdHeader Config Handle for library, services.
+ *
+ * @return Family specific error value.
+ *
+ */
+typedef AGESA_STATUS F_TDP_LIMIT_INIT (
+ IN TDP_LIMIT_FAMILY_SERVICES *TdpLimitServices,
+ IN UINT32 *PowerCeiling,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ );
+
+/// Reference to a Method.
+typedef F_TDP_LIMIT_INIT *PF_TDP_LIMIT_INIT;
+
+/**
+ * Provide the interface to the TDP limiting Family Specific Services.
+ *
+ * Use the methods or data in this struct to adapt the feature code to a specific cpu family or model (or stepping!).
+ * Each supported Family must provide an implementation for all methods in this interface, even if the
+ * implementation is a CommonReturn().
+ */
+struct _TDP_LIMIT_FAMILY_SERVICES {
+ UINT16 Revision; ///< Interface version
+ // Public Methods.
+ PF_TDP_LIMIT_IS_SUPPORTED IsTdpLimitSupported; ///< Method: Family specific call to check if TDP limiting is supported.
+ PF_TDP_LIMIT_INIT EnableTdpLimitOnSocket; ///< Method: Family specific call to enable TDP limiting.
+};
+
+
+/*----------------------------------------------------------------------------------------
+ * F U N C T I O N S P R O T O T Y P E
+ *----------------------------------------------------------------------------------------
+ */
+
+#endif // _CPU_TDP_LIMITING_H_
diff --git a/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuWhea.c b/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuWhea.c
new file mode 100644
index 0000000000..f41dca92aa
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f16kb/Proc/CPU/Feature/cpuWhea.c
@@ -0,0 +1,288 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * AMD WHEA Table Creation API, and related functions.
+ *
+ * Contains code that produce the ACPI WHEA related information.
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: CPU
+ * @e \$Revision: 84150 $ @e \$Date: 2012-12-12 15:46:25 -0600 (Wed, 12 Dec 2012) $
+ *
+ */
+/*
+ ******************************************************************************
+ *
+ * Copyright (c) 2008 - 2013, Advanced Micro Devices, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Advanced Micro Devices, Inc. nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ ******************************************************************************
+ */
+
+/*----------------------------------------------------------------------------------------
+ * M O D U L E S U S E D
+ *----------------------------------------------------------------------------------------
+ */
+#include "AGESA.h"
+#include "amdlib.h"
+#include "OptionWhea.h"
+#include "cpuLateInit.h"
+#include "heapManager.h"
+#include "cpuRegisters.h"
+#include "cpuFamilyTranslation.h"
+#include "Ids.h"
+#include "Filecode.h"
+CODE_GROUP (G3_DXE)
+RDATA_GROUP (G3_DXE)
+
+#define FILECODE PROC_CPU_FEATURE_CPUWHEA_FILECODE
+/*----------------------------------------------------------------------------------------
+ * D E F I N I T I O N S A N D M A C R O S
+ *---------------------------------------------------------------------------------------
+ */
+
+extern OPTION_WHEA_CONFIGURATION OptionWheaConfiguration; // global user config record
+
+/*----------------------------------------------------------------------------------------
+ * T Y P E D E F S A N D S T R U C T U R E S
+ *----------------------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------------------
+ * P R O T O T Y P E S O F L O C A L F U N C T I O N S
+ *----------------------------------------------------------------------------------------
+ */
+VOID
+STATIC
+CreateHestBank (
+ IN AMD_HEST_BANK *HestBankPtr,
+ IN UINT8 BankNum,
+ IN AMD_WHEA_INIT_DATA *WheaInitDataPtr
+ );
+
+AGESA_STATUS
+GetAcpiWheaStub (
+ IN OUT AMD_CONFIG_PARAMS *StdHeader,
+ IN OUT VOID **WheaMcePtr,
+ IN OUT VOID **WheaCmcPtr
+ );
+
+AGESA_STATUS
+GetAcpiWheaMain (
+ IN OUT AMD_CONFIG_PARAMS *StdHeader,
+ IN OUT VOID **WheaMcePtr,
+ IN OUT VOID **WheaCmcPtr
+ );
+
+/*----------------------------------------------------------------------------------------
+ * E X P O R T E D F U N C T I O N S
+ *----------------------------------------------------------------------------------------
+ */
+/*---------------------------------------------------------------------------------------*/
+/**
+ *
+ * It will create the ACPI table of WHEA and return the pointer to the table.
+ *
+ * @param[in, out] StdHeader Standard Head Pointer
+ * @param[in, out] WheaMcePtr Point to Whea Hest Mce table
+ * @param[in, out] WheaCmcPtr Point to Whea Hest Cmc table
+ *
+ * @retval AGESA_STATUS
+ */
+AGESA_STATUS
+CreateAcpiWhea (
+ IN OUT AMD_CONFIG_PARAMS *StdHeader,
+ IN OUT VOID **WheaMcePtr,
+ IN OUT VOID **WheaCmcPtr
+ )
+{
+ AGESA_TESTPOINT (TpProcCpuEntryWhea, StdHeader);
+ return ((*(OptionWheaConfiguration.WheaFeature)) (StdHeader, WheaMcePtr, WheaCmcPtr));
+}
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ *
+ * This is the default routine for use when the WHEA option is NOT requested.
+ *
+ * The option install process will create and fill the transfer vector with
+ * the address of the proper routine (Main or Stub). The link optimizer will
+ * strip out of the .DLL the routine that is not used.
+ *
+ * @param[in, out] StdHeader Standard Head Pointer
+ * @param[in, out] WheaMcePtr Point to Whea Hest Mce table
+ * @param[in, out] WheaCmcPtr Point to Whea Hest Cmc table
+ *
+ * @retval AGESA_STATUS
+ */
+
+AGESA_STATUS
+GetAcpiWheaStub (
+ IN OUT AMD_CONFIG_PARAMS *StdHeader,
+ IN OUT VOID **WheaMcePtr,
+ IN OUT VOID **WheaCmcPtr
+ )
+{
+ return AGESA_UNSUPPORTED;
+}
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ *
+ * It will create the ACPI tale of WHEA and return the pointer to the table.
+ *
+ * @param[in, out] StdHeader Standard Head Pointer
+ * @param[in, out] WheaMcePtr Point to Whea Hest Mce table
+ * @param[in, out] WheaCmcPtr Point to Whea Hest Cmc table
+ *
+ * @retval UINT32 AGESA_STATUS
+ */
+AGESA_STATUS
+GetAcpiWheaMain (
+ IN OUT AMD_CONFIG_PARAMS *StdHeader,
+ IN OUT VOID **WheaMcePtr,
+ IN OUT VOID **WheaCmcPtr
+ )
+{
+ UINT8 BankNum;
+ UINT8 Entries;
+ UINT16 HestMceTableSize;
+ UINT16 HestCmcTableSize;
+ UINT64 MsrData;
+ AMD_HEST_MCE_TABLE *HestMceTablePtr;
+ AMD_HEST_CMC_TABLE *HestCmcTablePtr;
+ AMD_HEST_BANK *HestBankPtr;
+ AMD_WHEA_INIT_DATA *WheaInitDataPtr;
+ ALLOCATE_HEAP_PARAMS AllocParams;
+ CPU_SPECIFIC_SERVICES *FamilySpecificServices;
+
+ FamilySpecificServices = NULL;
+
+ IDS_HDT_CONSOLE (CPU_TRACE, " WHEA is created\n");
+
+ // step 1: calculate Hest table size
+ LibAmdMsrRead (MSR_MCG_CAP, &MsrData, StdHeader);
+ BankNum = (UINT8) (((MSR_MCG_CAP_STRUCT *) (&MsrData))->Count);
+ if (BankNum == 0) {
+ return AGESA_ERROR;
+ }
+
+ GetCpuServicesOfCurrentCore ((CONST CPU_SPECIFIC_SERVICES **)&FamilySpecificServices, StdHeader);
+ FamilySpecificServices->GetWheaInitData (FamilySpecificServices, (CONST VOID **) &WheaInitDataPtr, &Entries, StdHeader);
+
+ ASSERT (WheaInitDataPtr != NULL);
+ if (WheaInitDataPtr == NULL) {
+ return AGESA_ERROR;
+ }
+
+ ASSERT (WheaInitDataPtr->HestBankNum <= BankNum);
+
+ HestMceTableSize = sizeof (AMD_HEST_MCE_TABLE) + WheaInitDataPtr->HestBankNum * sizeof (AMD_HEST_BANK);
+ HestCmcTableSize = sizeof (AMD_HEST_CMC_TABLE) + WheaInitDataPtr->HestBankNum * sizeof (AMD_HEST_BANK);
+
+ HestMceTablePtr = (AMD_HEST_MCE_TABLE *) *WheaMcePtr;
+ HestCmcTablePtr = (AMD_HEST_CMC_TABLE *) *WheaCmcPtr;
+
+ // step 2: allocate a buffer by callback function
+ if ((HestMceTablePtr == NULL) || (HestCmcTablePtr == NULL)) {
+ AllocParams.RequestedBufferSize = (UINT32) (HestMceTableSize + HestCmcTableSize);
+ AllocParams.BufferHandle = AMD_WHEA_BUFFER_HANDLE;
+ AllocParams.Persist = HEAP_SYSTEM_MEM;
+
+ AGESA_TESTPOINT (TpProcCpuBeforeAllocateWheaBuffer, StdHeader);
+ if (HeapAllocateBuffer (&AllocParams, StdHeader) != AGESA_SUCCESS) {
+ return AGESA_ERROR;
+ }
+ AGESA_TESTPOINT (TpProcCpuAfterAllocateWheaBuffer, StdHeader);
+
+ HestMceTablePtr = (AMD_HEST_MCE_TABLE *) AllocParams.BufferPtr;
+ HestCmcTablePtr = (AMD_HEST_CMC_TABLE *) ((UINT8 *) (HestMceTablePtr + 1) + (WheaInitDataPtr->HestBankNum * sizeof (AMD_HEST_BANK)));
+ }
+
+ // step 3: fill in Hest MCE table
+ HestMceTablePtr->TblLength = HestMceTableSize;
+ HestMceTablePtr->GlobCapInitDataLSD = WheaInitDataPtr->GlobCapInitDataLSD;
+ HestMceTablePtr->GlobCapInitDataMSD = WheaInitDataPtr->GlobCapInitDataMSD;
+ HestMceTablePtr->GlobCtrlInitDataLSD = WheaInitDataPtr->GlobCtrlInitDataLSD;
+ HestMceTablePtr->GlobCtrlInitDataMSD = WheaInitDataPtr->GlobCtrlInitDataMSD;
+ HestMceTablePtr->NumHWBanks = WheaInitDataPtr->HestBankNum;
+
+ HestBankPtr = (AMD_HEST_BANK *) (HestMceTablePtr + 1);
+ CreateHestBank (HestBankPtr, WheaInitDataPtr->HestBankNum, WheaInitDataPtr);
+
+ // step 4: fill in Hest CMC table
+ HestCmcTablePtr->NumHWBanks = WheaInitDataPtr->HestBankNum;
+ HestCmcTablePtr->TblLength = HestCmcTableSize;
+
+ HestBankPtr = (AMD_HEST_BANK *) (HestCmcTablePtr + 1);
+ CreateHestBank (HestBankPtr, WheaInitDataPtr->HestBankNum, WheaInitDataPtr);
+
+ // step 5: fill in the incoming structure
+ *WheaMcePtr = HestMceTablePtr;
+ *WheaCmcPtr = HestCmcTablePtr;
+
+ return (AGESA_SUCCESS);
+}
+
+/*---------------------------------------------------------------------------------------
+ * L O C A L F U N C T I O N S
+ *---------------------------------------------------------------------------------------
+ */
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ *
+ * It will create Bank structure for Hest table
+ *
+ * @param[in] HestBankPtr Pointer to the Hest Back structure
+ * @param[in] BankNum The number of Bank
+ * @param[in] WheaInitDataPtr Pointer to the AMD_WHEA_INIT_DATA structure
+ *
+ */
+VOID
+STATIC
+CreateHestBank (
+ IN AMD_HEST_BANK *HestBankPtr,
+ IN UINT8 BankNum,
+ IN AMD_WHEA_INIT_DATA *WheaInitDataPtr
+ )
+{
+ UINT8 BankIndex;
+ for (BankIndex = 0; BankIndex < BankNum; BankIndex++) {
+ HestBankPtr->BankNum = BankIndex;
+ HestBankPtr->ClrStatusOnInit = WheaInitDataPtr->ClrStatusOnInit;
+ HestBankPtr->StatusDataFormat = WheaInitDataPtr->StatusDataFormat;
+ HestBankPtr->ConfWriteEn = WheaInitDataPtr->ConfWriteEn;
+ HestBankPtr->CtrlRegMSRAddr = WheaInitDataPtr->HestBankInitData[BankIndex].CtrlRegMSRAddr;
+ HestBankPtr->CtrlInitDataLSD = WheaInitDataPtr->HestBankInitData[BankIndex].CtrlInitDataLSD;
+ HestBankPtr->CtrlInitDataMSD = WheaInitDataPtr->HestBankInitData[BankIndex].CtrlInitDataMSD;
+ HestBankPtr->StatRegMSRAddr = WheaInitDataPtr->HestBankInitData[BankIndex].StatRegMSRAddr;
+ HestBankPtr->AddrRegMSRAddr = WheaInitDataPtr->HestBankInitData[BankIndex].AddrRegMSRAddr;
+ HestBankPtr->MiscRegMSRAddr = WheaInitDataPtr->HestBankInitData[BankIndex].MiscRegMSRAddr;
+ HestBankPtr++;
+ }
+}
+