summaryrefslogtreecommitdiff
path: root/Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiCpuS3Lib
diff options
context:
space:
mode:
authorGuo Mang <mang.guo@intel.com>2016-12-22 19:41:14 +0800
committerGuo Mang <mang.guo@intel.com>2016-12-26 19:15:02 +0800
commita674eea1c47a6aa0170b2beb07d4f2bbefc798e0 (patch)
tree3db2b004775c74c311c7c5b7b3998f0c6dc91c32 /Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiCpuS3Lib
parentf0a77159beb39438f311993bf6cd4136aa7e02fc (diff)
downloadedk2-platforms-a674eea1c47a6aa0170b2beb07d4f2bbefc798e0.tar.xz
BroxtonSiPkg: Add Cpu Include file and Library
Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Guo Mang <mang.guo@intel.com>
Diffstat (limited to 'Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiCpuS3Lib')
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiCpuS3Lib/CpuS3.h229
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiCpuS3Lib/CpuS3Lib.c753
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiCpuS3Lib/Ia32/MpEqu.h45
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiCpuS3Lib/Ia32/MpEqu.inc49
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiCpuS3Lib/Ia32/MpFuncs.S210
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiCpuS3Lib/Ia32/MpFuncs.asm206
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiCpuS3Lib/PeiCpuS3Lib.inf59
7 files changed, 1551 insertions, 0 deletions
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiCpuS3Lib/CpuS3.h b/Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiCpuS3Lib/CpuS3.h
new file mode 100644
index 0000000000..3ab1813b75
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiCpuS3Lib/CpuS3.h
@@ -0,0 +1,229 @@
+/** @file
+ Definitions for S3 Resume.
+
+ Copyright (c) 2014 - 2016, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _CPU_S3_
+#define _CPU_S3_
+
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/SynchronizationLib.h>
+#include <Library/TimerLib.h>
+#include <Library/HobLib.h>
+#include <Library/CpuPlatformLib.h>
+#include <Private/Library/CpuCommonLib.h>
+#include <Ppi/SmmAccess.h>
+#include <Ppi/MasterBootMode.h>
+#include <Ppi/EndOfPeiPhase.h>
+#include <Ppi/CpuPolicy.h>
+#include "CpuAccess.h"
+
+#define VacantFlag 0x00
+#define NotVacantFlag 0xff
+
+#define MICROSECOND 10
+
+#define MAXIMUM_CPU_NUMBER 0x40
+#define STACK_SIZE_PER_PROC 0x8000
+
+#define MAXIMUM_CPU_S3_TABLE_SIZE 0x1000
+
+#define IO_APIC_INDEX_REGISTER 0xFEC00000
+#define IO_APIC_DATA_REGISTER 0xFEC00010
+
+extern UINTN FixedMtrrNumber;
+extern UINTN MtrrDefTypeNumber;
+
+typedef struct {
+ UINT16 Index;
+ UINT64 Value;
+} EFI_MTRR_VALUES;
+
+typedef struct {
+ UINT32 ApicId;
+ UINT32 MsrIndex;
+ UINT64 MsrValue;
+} MP_CPU_S3_SCRIPT_DATA;
+
+typedef struct {
+ UINT32 S3BootScriptTable;
+ UINT32 S3BspMtrrTable;
+ UINT32 VirtualWireMode;
+} MP_CPU_S3_DATA_POINTER;
+
+typedef struct {
+ UINT32 Lock;
+ UINT32 StackStart;
+ UINT32 StackSize;
+ UINT32 ApFunction;
+ IA32_DESCRIPTOR GdtrProfile;
+ IA32_DESCRIPTOR IdtrProfile;
+ UINT32 BufferStart;
+ UINT32 PmodeOffset;
+ UINT32 AcpiCpuDataAddress;
+ UINT32 MtrrValuesAddress;
+ UINT32 FinishedCount;
+ UINT32 WakeupCount;
+ UINT32 SerializeLock;
+ MP_CPU_S3_SCRIPT_DATA *S3BootScriptTable;
+ UINT32 StartState;
+ UINT32 VirtualWireMode;
+ VOID (*SemaphoreCheck)(UINT32 *SemaphoreAddress);
+ UINT32 McuLoadCount;
+ IN CONST EFI_PEI_SERVICES **PeiServices;
+ UINT64 CpuPerfCtrlValue;
+ SI_CPU_POLICY_PPI *SiCpuPolicyPpi;
+} MP_CPU_EXCHANGE_INFO;
+
+/**
+ Get protected mode code offset
+
+ @retval Offset of protected mode code
+
+**/
+VOID *
+S3AsmGetPmodeOffset (
+ VOID
+ );
+
+/**
+ Get code offset of SemaphoreCheck
+
+ @retval Offset of SemaphoreCheck
+
+**/
+UINT32
+S3AsmGetSemaphoreCheckOffset (
+ VOID
+ );
+
+/**
+ Read MTRR settings
+
+ @param[in] MtrrValues Buffer to store MTRR settings
+
+**/
+VOID
+ReadMtrrRegisters (
+ UINT64 *MtrrValues
+ );
+
+/**
+ Syncup MTRR settings between all processors
+
+ @param[in] MtrrValues Buffer to store MTRR settings
+
+**/
+VOID
+MpMtrrSynchUp (
+ UINT64 *MtrrValues
+ );
+
+/**
+ Set MTRR registers
+
+ @param[in] MtrrArray Buffer with MTRR settings
+
+**/
+VOID
+SetMtrrRegisters (
+ IN EFI_MTRR_VALUES *MtrrArray
+ );
+
+#ifdef EFI_DEBUG
+/**
+ Print MTRR settings in debug build BIOS
+
+ @param[in] MtrrArray Buffer with MTRR settings
+
+**/
+VOID
+ShowMtrrRegisters (
+ IN EFI_MTRR_VALUES *MtrrArray
+ );
+#endif
+
+/**
+ This will check if the microcode address is valid for this processor, and if so, it will
+ load it to the processor.
+
+ @param[in] ExchangeInfo Pointer to the exchange info buffer for output.
+ @param[in] MicrocodeAddress The address of the microcode update binary (in memory).
+ @param[out] FailedRevision The microcode revision that fails to be loaded.
+
+ @retval EFI_SUCCESS A new microcode update is loaded.
+ @retval Other Due to some reason, no new microcode update is loaded.
+
+**/
+EFI_STATUS
+InitializeMicrocode (
+ IN MP_CPU_EXCHANGE_INFO *ExchangeInfo,
+ IN CPU_MICROCODE_HEADER *MicrocodeAddress,
+ OUT UINT32 *FailedRevision
+ );
+
+///
+/// Functions shared in MP/HT drivers
+///
+/**
+ Send interrupt to CPU
+
+ @param[in] BroadcastMode Interrupt broadcast mode
+ @param[in] ApicID APIC ID for sending interrupt
+ @param[in] VectorNumber Vector number
+ @param[in] DeliveryMode Interrupt delivery mode
+ @param[in] TriggerMode Interrupt trigger mode
+ @param[in] Assert Interrupt pin polarity
+
+ @retval EFI_INVALID_PARAMETER Input parameter not correct
+ @retval EFI_NOT_READY There was a pending interrupt
+ @retval EFI_SUCCESS Interrupt sent successfully
+
+**/
+EFI_STATUS
+SendInterrupt (
+ IN UINT32 BroadcastMode,
+ IN UINT32 ApicID,
+ IN UINT32 VectorNumber,
+ IN UINT32 DeliveryMode,
+ IN UINT32 TriggerMode,
+ IN BOOLEAN Assert
+ );
+
+/**
+ Programs Local APIC registers for virtual wire mode.
+
+ @param[in] BSP Is this BSP?
+
+**/
+VOID
+ProgramXApic (
+ BOOLEAN BSP
+ );
+
+/**
+ Get address map of S3RendezvousFunnelProc.
+
+ @retval AddressMap Output buffer for address map information
+
+**/
+VOID *
+S3AsmGetAddressMap (
+ VOID
+ );
+
+#endif
+
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiCpuS3Lib/CpuS3Lib.c b/Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiCpuS3Lib/CpuS3Lib.c
new file mode 100644
index 0000000000..8c4c8f34ee
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiCpuS3Lib/CpuS3Lib.c
@@ -0,0 +1,753 @@
+/** @file
+ Cpu S3 library running on S3 resume paths.
+
+ Copyright (c) 2014 - 2016, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Private/Library/CpuS3Lib.h>
+#include "CpuS3.h"
+#include <Library/CpuPolicyLib.h>
+#include <Library/PostCodeLib.h>
+
+extern EFI_GUID gSmramCpuDataHeaderGuid;
+extern EFI_GUID gPeiAcpiCpuDataGuid;
+
+typedef VOID (*S3_AP_PROCEDURE) (
+ MP_CPU_EXCHANGE_INFO *ExchangeInfo,
+ UINT64 *MtrrValues
+ );
+
+/**
+ This function handles CPU S3 resume task at the end of PEI
+
+ @param[in] PeiServices Pointer to PEI Services Table.
+ @param[in] NotifyDesc Pointer to the descriptor for the Notification event that
+ caused this function to execute.
+ @param[in] Ppi Pointer to the PPI data associated with this function.
+
+ @retval EFI_STATUS Always return EFI_SUCCESS
+
+**/
+STATIC
+EFI_STATUS
+CpuS3ResumeAtEndOfPei (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDesc,
+ IN VOID *Ppi
+ );
+
+
+STATIC EFI_PEI_NOTIFY_DESCRIPTOR mCpuS3ResumeNotifyDesc = {
+ (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEfiEndOfPeiSignalPpiGuid,
+ CpuS3ResumeAtEndOfPei
+};
+
+
+/**
+ Restore all MSR settings
+
+ @param[in] ScriptTable Contain the MSR settings that will be restored.
+
+**/
+VOID
+InitializeFeatures (
+ IN MP_CPU_S3_SCRIPT_DATA *ScriptTable
+ )
+{
+ EFI_CPUID_REGISTER CpuidRegisters;
+ UINT32 ApicId;
+ UINT8 SkipMsr;
+
+ //
+ // Restore all the MSRs for processor
+ //
+ AsmCpuid (
+ CPUID_VERSION_INFO,
+ &CpuidRegisters.RegEax,
+ &CpuidRegisters.RegEbx,
+ &CpuidRegisters.RegEcx,
+ &CpuidRegisters.RegEdx
+ );
+ ApicId = (CpuidRegisters.RegEbx >> 24);
+
+ while (ScriptTable->MsrIndex != 0) {
+ if (ApicId == ScriptTable->ApicId) {
+ SkipMsr = 0;
+ if ((ScriptTable->MsrIndex == MSR_PMG_CST_CONFIG) && (AsmReadMsr64 (MSR_PMG_CST_CONFIG) & B_CST_CONTROL_LOCK)) {
+ SkipMsr = 1;
+ }
+ if ((ScriptTable->MsrIndex == MSR_IA32_FEATURE_CONTROL) && (AsmReadMsr64 (MSR_IA32_FEATURE_CONTROL) & B_MSR_IA32_FEATURE_CONTROL_LOCK)) {
+ SkipMsr = 1;
+ }
+ if (SkipMsr == 0) {
+ AsmWriteMsr64 (ScriptTable->MsrIndex, ScriptTable->MsrValue);
+ }
+ }
+ ScriptTable++;
+ }
+}
+
+
+/**
+ Restore all MSR settings with debug message output
+
+ @param[in] ScriptTable Script table contain all MSR settings that will be restored
+
+**/
+VOID
+InitializeFeaturesLog (
+ IN MP_CPU_S3_SCRIPT_DATA *ScriptTable
+ )
+{
+ EFI_CPUID_REGISTER CpuidRegisters;
+ UINT32 ApicId;
+ BOOLEAN SkipMsr;
+
+ PostCode (0xC41);
+
+ //
+ // Restore all the MSRs for processor
+ //
+ AsmCpuid (
+ CPUID_VERSION_INFO,
+ &CpuidRegisters.RegEax,
+ &CpuidRegisters.RegEbx,
+ &CpuidRegisters.RegEcx,
+ &CpuidRegisters.RegEdx
+ );
+ ApicId = (CpuidRegisters.RegEbx >> 24);
+
+ while (ScriptTable->MsrIndex != 0) {
+ if (ApicId == ScriptTable->ApicId) {
+ DEBUG ((DEBUG_INFO, "MSR Index - %x, MSR value - %x\n", ScriptTable->MsrIndex, ScriptTable->MsrValue));
+ SkipMsr = FALSE;
+ if ((ScriptTable->MsrIndex == MSR_PMG_CST_CONFIG) && (AsmReadMsr64 (MSR_PMG_CST_CONFIG) & B_CST_CONTROL_LOCK)) {
+ SkipMsr = TRUE;
+ }
+ if ((ScriptTable->MsrIndex == MSR_IA32_FEATURE_CONTROL) && (AsmReadMsr64 (MSR_IA32_FEATURE_CONTROL) & B_MSR_IA32_FEATURE_CONTROL_LOCK)) {
+ SkipMsr = TRUE;
+ }
+ if (ScriptTable->MsrIndex == MSR_IA32_DEBUG_INTERFACE) {
+ //
+ // Debug interface is supported if CPUID (EAX=1): ECX[11] = 1
+ //
+ if ((CpuidRegisters.RegEcx & BIT11) && (AsmReadMsr64 (MSR_IA32_DEBUG_INTERFACE) & B_DEBUG_INTERFACE_LOCK)) {
+ SkipMsr = TRUE;
+ }
+ }
+ if (!SkipMsr) {
+ AsmWriteMsr64 (ScriptTable->MsrIndex, ScriptTable->MsrValue);
+ }
+ }
+ ScriptTable++;
+ }
+ PostCode (0xC44);
+}
+
+
+/**
+ AP initialization
+
+ @param[in] ExchangeInfo Pointer to the exchange info buffer for output.
+ @param[in] MtrrValues Buffer contains MTRR settings
+
+**/
+VOID
+MPRendezvousProcedure (
+ MP_CPU_EXCHANGE_INFO *ExchangeInfo,
+ UINT64 *MtrrValues
+ )
+{
+ EFI_STATUS Status;
+ UINT32 FailedRevision;
+ ACPI_CPU_DATA *AcpiCpuData;
+ MP_CPU_S3_DATA_POINTER *CpuS3DataPtr;
+ EFI_CPUID_REGISTER CpuidRegisters;
+ CPU_CONFIG *CpuConfig;
+
+ Status = GetConfigBlock ((CONFIG_BLOCK_TABLE_HEADER *) ExchangeInfo->SiCpuPolicyPpi, &gCpuConfigGuid , (VOID *) &CpuConfig);
+ ASSERT_EFI_ERROR (Status);
+
+ AsmCpuid (
+ CPUID_VERSION_INFO,
+ &CpuidRegisters.RegEax,
+ &CpuidRegisters.RegEbx,
+ &CpuidRegisters.RegEcx,
+ &CpuidRegisters.RegEdx
+ );
+
+ //
+ // Init XMM support on all APs
+ //
+ XmmInit ();
+
+ //
+ // Switch AP speed to BSP speed
+ //
+ if ((CpuidRegisters.RegEcx & B_CPUID_VERSION_INFO_ECX_EIST) != 0) {
+ AsmWriteMsr64 (MSR_IA32_PERF_CTRL, ExchangeInfo->CpuPerfCtrlValue);
+ }
+
+ AcpiCpuData = (ACPI_CPU_DATA *) (ExchangeInfo->AcpiCpuDataAddress);
+
+ ProgramXApic (FALSE);
+
+ InitializeFeatures (ExchangeInfo->S3BootScriptTable);
+
+ InterlockedIncrement (&(ExchangeInfo->SerializeLock));
+ while (ExchangeInfo->SerializeLock < AcpiCpuData->NumberOfCpus) {
+ CpuPause ();
+ }
+
+ InitializeMicrocode (
+ ExchangeInfo,
+ (CPU_MICROCODE_HEADER *) (UINTN) CpuConfig->MicrocodePatchAddress,
+ &FailedRevision
+ );
+
+ ProcessorsPrefetcherInitialization (
+ CpuConfig->MlcStreamerPrefetcher,
+ CpuConfig->MlcSpatialPrefetcher
+ );
+
+ //
+ // wait till all CPUs done the Microcode Load
+ //
+ while (ExchangeInfo->McuLoadCount < AcpiCpuData->NumberOfCpus) {
+ CpuPause ();
+ }
+
+ MpMtrrSynchUp (MtrrValues);
+
+ InterlockedIncrement (&(ExchangeInfo->FinishedCount));
+
+ //
+ // Sempahore check loop executed in memory
+ //
+ (*ExchangeInfo->SemaphoreCheck) (&ExchangeInfo->FinishedCount);
+
+ InterlockedIncrement (&(ExchangeInfo->WakeupCount));
+
+ //
+ // Restore the MTRR programmed before OS boot
+ //
+ CpuS3DataPtr = (MP_CPU_S3_DATA_POINTER *) (UINTN) AcpiCpuData->CpuPrivateData;
+ SetMtrrRegisters ((EFI_MTRR_VALUES *) CpuS3DataPtr->S3BspMtrrTable);
+
+ while (ExchangeInfo->WakeupCount < AcpiCpuData->NumberOfCpus - 1) {
+ CpuPause ();
+ }
+
+ InterlockedIncrement (&(ExchangeInfo->FinishedCount));
+}
+
+
+/**
+ Wake up all the application processors
+
+ @param[in] PeiServices Indirect reference to the PEI Services Table
+ @param[in] AcpiCpuData Pointer to ACPI_CPU_DATA structure
+ @param[in] MtrrValues Pointer to a buffer which stored MTRR settings
+
+ @retval EFI_SUCCESS APs are successfully waked up
+
+**/
+EFI_STATUS
+S3WakeUpAps (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ ACPI_CPU_DATA *AcpiCpuData,
+ UINT64 *MtrrValues,
+ S3_AP_PROCEDURE Function
+ )
+{
+ EFI_PHYSICAL_ADDRESS WakeUpBuffer;
+ MP_CPU_EXCHANGE_INFO *ExchangeInfo;
+ MP_CPU_S3_DATA_POINTER *CpuS3DataPtr;
+
+ PostCode (0xC45);
+ WakeUpBuffer = AcpiCpuData->WakeUpBuffer;
+ CopyMem ((VOID *) (UINTN) WakeUpBuffer, S3AsmGetAddressMap (), 0x1000 - 0x200);
+
+ ExchangeInfo = (MP_CPU_EXCHANGE_INFO *) (UINTN) (WakeUpBuffer + (0x1000 - 0x200));
+
+ ExchangeInfo->Lock = 0;
+ ExchangeInfo->StackStart = (UINTN) AcpiCpuData->StackAddress;
+ ExchangeInfo->StackSize = STACK_SIZE_PER_PROC;
+ ExchangeInfo->ApFunction = (UINT32) Function;
+ ExchangeInfo->BufferStart = (UINT32) WakeUpBuffer;
+ ExchangeInfo->PmodeOffset = (UINT32) (S3AsmGetPmodeOffset ());
+ ExchangeInfo->SemaphoreCheck = (VOID (*)(UINT32 *)) (S3AsmGetSemaphoreCheckOffset () + (UINT32) WakeUpBuffer);
+ ExchangeInfo->AcpiCpuDataAddress = (UINT32) AcpiCpuData;
+ ExchangeInfo->MtrrValuesAddress = (UINT32) MtrrValues;
+ ExchangeInfo->FinishedCount = (UINT32) 0;
+ ExchangeInfo->SerializeLock = (UINT32) 0;
+ ExchangeInfo->StartState = (UINT32) 0;
+
+ CpuS3DataPtr = (MP_CPU_S3_DATA_POINTER *) (UINTN) AcpiCpuData->CpuPrivateData;
+ ExchangeInfo->S3BootScriptTable = (MP_CPU_S3_SCRIPT_DATA *) (UINTN) CpuS3DataPtr->S3BootScriptTable;
+ ExchangeInfo->VirtualWireMode = CpuS3DataPtr->VirtualWireMode;
+ ExchangeInfo->PeiServices = PeiServices;
+ ExchangeInfo->CpuPerfCtrlValue = AsmReadMsr64 (MSR_IA32_PERF_CTRL);
+
+ ExchangeInfo->SiCpuPolicyPpi = NULL;
+ PeiServicesLocatePpi (
+ &gSiCpuPolicyPpiGuid,
+ 0,
+ NULL,
+ (VOID **) &(ExchangeInfo->SiCpuPolicyPpi)
+ );
+
+ CopyMem (
+ (VOID *) (UINTN) &ExchangeInfo->GdtrProfile,
+ (VOID *) (UINTN) AcpiCpuData->GdtrProfile,
+ sizeof (IA32_DESCRIPTOR)
+ );
+ CopyMem (
+ (VOID *) (UINTN) &ExchangeInfo->IdtrProfile,
+ (VOID *) (UINTN) AcpiCpuData->IdtrProfile,
+ sizeof (IA32_DESCRIPTOR)
+ );
+
+ DEBUG ((DEBUG_INFO, "Cpu S3 Bootscript at %08X\n", (UINT32) ExchangeInfo->S3BootScriptTable));
+
+ //
+ // Don't touch MPCPU private data
+ // Here we use ExchangeInfo instead
+ //
+ //
+ // Send INIT IPI - SIPI to all APs
+ //
+ SendInterrupt (
+ BROADCAST_MODE_ALL_EXCLUDING_SELF,
+ 0,
+ 0,
+ DELIVERY_MODE_INIT,
+ TRIGGER_MODE_EDGE,
+ TRUE
+ );
+
+ MicroSecondDelay (10 * STALL_ONE_MILLI_SECOND); //< 10ms
+
+ SendInterrupt (
+ BROADCAST_MODE_ALL_EXCLUDING_SELF,
+ 0,
+ (UINT32) RShiftU64 (WakeUpBuffer, 12),
+ DELIVERY_MODE_SIPI,
+ TRIGGER_MODE_EDGE,
+ TRUE
+ );
+
+ MicroSecondDelay (200 * STALL_ONE_MICRO_SECOND); //< 200us
+
+ SendInterrupt (
+ BROADCAST_MODE_ALL_EXCLUDING_SELF,
+ 0,
+ (UINT32) RShiftU64 (WakeUpBuffer, 12),
+ DELIVERY_MODE_SIPI,
+ TRIGGER_MODE_EDGE,
+ TRUE
+ );
+
+ MicroSecondDelay (200 * STALL_ONE_MICRO_SECOND); //< 200us
+ PostCode (0xC48);
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ This routine is used to search SMRAM and get SmramCpuData point.
+
+ @param[in] PeiServices PEI services global pointer
+ @param[in] SmmAccessPpi SmmAccess PPI instance
+
+ @retval SmramCpuData The pointer of CPU information in SMRAM.
+
+**/
+STATIC
+SMRAM_CPU_DATA *
+GetSmmCpuData (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ IN PEI_SMM_ACCESS_PPI *SmmAccessPpi
+ )
+{
+ EFI_SMRAM_DESCRIPTOR *SmramRanges;
+ UINTN SmramRangeCount;
+ UINTN Size;
+ EFI_STATUS Status;
+ UINT32 Address;
+ SMRAM_CPU_DATA *SmramCpuData;
+
+ //
+ // Get all SMRAM range
+ //
+ Size = 0;
+ Status = SmmAccessPpi->GetCapabilities ((EFI_PEI_SERVICES **) PeiServices, SmmAccessPpi, &Size, NULL);
+ ASSERT (Status == EFI_BUFFER_TOO_SMALL);
+
+ Status = PeiServicesAllocatePool (
+ Size,
+ (VOID **) &SmramRanges
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = SmmAccessPpi->GetCapabilities ((EFI_PEI_SERVICES **) PeiServices, SmmAccessPpi, &Size, SmramRanges);
+ ASSERT_EFI_ERROR (Status);
+
+ Size /= sizeof (*SmramRanges);
+ SmramRangeCount = Size;
+
+ //
+ // We assume TSEG is the last range of SMRAM in SmramRanges
+ //
+ SmramRanges += SmramRangeCount - 1;
+
+ DEBUG ((DEBUG_INFO, "TsegBase - %x\n", SmramRanges->CpuStart));
+ DEBUG ((DEBUG_INFO, "TsegTop - %x\n", SmramRanges->CpuStart + SmramRanges->PhysicalSize));
+
+ //
+ // Search SMRAM on page alignment for the SMMNVS signature
+ //
+ for (Address = (UINT32) (SmramRanges->CpuStart + SmramRanges->PhysicalSize - EFI_PAGE_SIZE);
+ Address >= (UINT32) SmramRanges->CpuStart;
+ Address -= EFI_PAGE_SIZE
+ ) {
+ SmramCpuData = (SMRAM_CPU_DATA *) (UINTN) Address;
+ if (CompareGuid (&SmramCpuData->HeaderGuid, &gSmramCpuDataHeaderGuid)) {
+ return SmramCpuData;
+ }
+ }
+
+ ASSERT (FALSE);
+
+ return NULL;
+}
+
+/**
+ This routine is restore the CPU information from SMRAM to original reserved memory region.
+
+ @param[in] PeiServices PEI services global pointer
+
+ @retval AcpiCpuData The pointer of CPU information in reserved memory.
+
+**/
+ACPI_CPU_DATA *
+RestoreSmramCpuData (
+ IN CONST EFI_PEI_SERVICES **PeiServices
+ )
+{
+ PEI_SMM_ACCESS_PPI *SmmAccessPpi;
+ SMRAM_CPU_DATA *SmramCpuData;
+ EFI_STATUS Status;
+ ACPI_CPU_DATA *AcpiCpuData;
+ MP_CPU_S3_DATA_POINTER *CpuS3DataPtr;
+ IA32_DESCRIPTOR *Idtr;
+ IA32_DESCRIPTOR *Gdtr;
+ UINTN Index;
+
+ Status = PeiServicesLocatePpi (
+ &gPeiSmmAccessPpiGuid,
+ 0,
+ NULL,
+ (VOID **) &SmmAccessPpi
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Open all SMM regions
+ //
+ Index = 0;
+ do {
+ Status = SmmAccessPpi->Open ((EFI_PEI_SERVICES **) PeiServices, SmmAccessPpi, Index);
+ Index++;
+ } while (!EFI_ERROR (Status));
+
+ SmramCpuData = GetSmmCpuData ((CONST EFI_PEI_SERVICES **) PeiServices, SmmAccessPpi);
+ if (SmramCpuData == NULL) {
+ ASSERT (FALSE);
+ return NULL;
+ }
+ DEBUG ((DEBUG_INFO, "CpuS3 SmramCpuData - 0x%x \n", SmramCpuData));
+ DEBUG ((DEBUG_INFO, "SmramCpuData->GdtrProfileSize - %x\n", SmramCpuData->GdtrProfileSize));
+ DEBUG ((DEBUG_INFO, "SmramCpuData->GdtSize - %x\n", SmramCpuData->GdtSize));
+ DEBUG ((DEBUG_INFO, "SmramCpuData->IdtrProfileSize - %x\n", SmramCpuData->IdtrProfileSize));
+ DEBUG ((DEBUG_INFO, "SmramCpuData->IdtSize - %x\n", SmramCpuData->IdtSize));
+ DEBUG ((DEBUG_INFO, "SmramCpuData->CpuPrivateDataSize - %x\n", SmramCpuData->CpuPrivateDataSize));
+ DEBUG ((DEBUG_INFO, "SmramCpuData->S3BootScriptTableSize - %x\n", SmramCpuData->S3BootScriptTableSize));
+ DEBUG ((DEBUG_INFO, "SmramCpuData->S3BspMtrrTableSize - %x\n", SmramCpuData->S3BspMtrrTableSize));
+ DEBUG ((DEBUG_INFO, "SmramCpuData->GdtrProfileOffset - %x\n", SmramCpuData->GdtrProfileOffset));
+ DEBUG ((DEBUG_INFO, "SmramCpuData->GdtOffset - %x\n", SmramCpuData->GdtOffset));
+ DEBUG ((DEBUG_INFO, "SmramCpuData->IdtrProfileOffset - %x\n", SmramCpuData->IdtrProfileOffset));
+ DEBUG ((DEBUG_INFO, "SmramCpuData->IdtOffset - %x\n", SmramCpuData->IdtOffset));
+ DEBUG ((DEBUG_INFO, "SmramCpuData->CpuPrivateDataOffset - %x\n", SmramCpuData->CpuPrivateDataOffset));
+ DEBUG ((DEBUG_INFO, "SmramCpuData->S3BootScriptTableOffset - %x\n", SmramCpuData->S3BootScriptTableOffset));
+ DEBUG ((DEBUG_INFO, "SmramCpuData->S3BspMtrrTableOffset - %x\n", SmramCpuData->S3BspMtrrTableOffset));
+
+ //
+ // Start restore data to NVS
+ //
+ AcpiCpuData = (ACPI_CPU_DATA *) (UINTN) SmramCpuData->AcpiCpuPointer;
+ CopyMem (AcpiCpuData, &SmramCpuData->AcpiCpuData, sizeof (ACPI_CPU_DATA));
+
+ CopyMem (
+ (VOID *) (UINTN) AcpiCpuData->GdtrProfile,
+ (UINT8 *) SmramCpuData + SmramCpuData->GdtrProfileOffset,
+ SmramCpuData->GdtrProfileSize
+ );
+ Gdtr = (IA32_DESCRIPTOR *) (UINTN) AcpiCpuData->GdtrProfile;
+ CopyMem (
+ (VOID *) (UINTN) Gdtr->Base,
+ (UINT8 *) SmramCpuData + SmramCpuData->GdtOffset,
+ SmramCpuData->GdtSize
+ );
+ CopyMem (
+ (VOID *) (UINTN) AcpiCpuData->IdtrProfile,
+ (UINT8 *) SmramCpuData + SmramCpuData->IdtrProfileOffset,
+ SmramCpuData->IdtrProfileSize
+ );
+ Idtr = (IA32_DESCRIPTOR *) (UINTN) AcpiCpuData->IdtrProfile;
+ CopyMem (
+ (VOID *) (UINTN) Idtr->Base,
+ (UINT8 *) SmramCpuData + SmramCpuData->IdtOffset,
+ SmramCpuData->IdtSize
+ );
+ CopyMem (
+ (VOID *) (UINTN) AcpiCpuData->CpuPrivateData,
+ (UINT8 *) SmramCpuData + SmramCpuData->CpuPrivateDataOffset,
+ SmramCpuData->CpuPrivateDataSize
+ );
+ CpuS3DataPtr = (MP_CPU_S3_DATA_POINTER *) (UINTN) AcpiCpuData->CpuPrivateData;
+ CopyMem (
+ (VOID *) (UINTN) CpuS3DataPtr->S3BootScriptTable,
+ (UINT8 *) SmramCpuData + SmramCpuData->S3BootScriptTableOffset,
+ SmramCpuData->S3BootScriptTableSize
+ );
+ CopyMem (
+ (VOID *) (UINTN) CpuS3DataPtr->S3BspMtrrTable,
+ (UINT8 *) SmramCpuData + SmramCpuData->S3BspMtrrTableOffset,
+ SmramCpuData->S3BspMtrrTableSize
+ );
+ //
+ // Close all SMM regions
+ //
+ Index = 0;
+ do {
+ Status = SmmAccessPpi->Close ((EFI_PEI_SERVICES **) PeiServices, SmmAccessPpi, Index);
+ Index++;
+ } while (!EFI_ERROR (Status));
+
+ return AcpiCpuData;
+}
+
+
+/**
+ Cpu initialization called during S3 resume to take care
+ of CPU related activities in PEI phase
+
+ @param[in] PeiServices Indirect reference to the PEI Services Table
+
+ @retval EFI_SUCCESS Multiple processors are intialized successfully.
+
+**/
+EFI_STATUS
+S3InitializeCpu (
+ IN CONST EFI_PEI_SERVICES **PeiServices
+ )
+{
+ EFI_STATUS Status;
+ ACPI_CPU_DATA *AcpiCpuData;
+ UINT64 *MtrrValues;
+ MP_CPU_S3_DATA_POINTER *CpuS3DataPtr;
+ UINTN VariableMtrrNumber;
+ EFI_PHYSICAL_ADDRESS WakeUpBuffer;
+ MP_CPU_EXCHANGE_INFO *ExchangeInfo;
+ UINT32 FailedRevision;
+ VOID *Hob;
+ EFI_BOOT_MODE BootMode;
+ CPU_CONFIG *CpuConfig;
+
+ Status = PeiServicesGetBootMode (&BootMode);
+ DEBUG ((DEBUG_INFO, "CPU: BootMode = %X\n", BootMode));
+ if ((Status == EFI_SUCCESS) && (BootMode != BOOT_ON_S3_RESUME)) {
+ DEBUG ((DEBUG_INFO,"CPU: Normal Boot\n"));
+ return EFI_SUCCESS;
+ }
+
+ DEBUG((DEBUG_INFO, "S3InitializeCpu Start \n"));
+ PostCode (0xC40);
+
+ //
+ // Restore ACPI Nvs data from SMRAM
+ //
+ AcpiCpuData = RestoreSmramCpuData ((CONST EFI_PEI_SERVICES **) PeiServices);
+ if (AcpiCpuData == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ DEBUG ((DEBUG_INFO, "CpuS3 RestoreSmramCpuData - 0x%x \n", AcpiCpuData));
+
+ AcpiCpuData->S3BootPath = TRUE;
+
+ CpuS3DataPtr = (MP_CPU_S3_DATA_POINTER *) (UINTN) AcpiCpuData->CpuPrivateData;
+
+ VariableMtrrNumber = (UINTN) ((UINT64) AsmReadMsr64 (IA32_MTRR_CAP) & B_IA32_MTRR_VARIABLE_SUPPORT) * 2;
+ Status = PeiServicesAllocatePool (
+ (FixedMtrrNumber + MtrrDefTypeNumber + VariableMtrrNumber) * sizeof (UINT64),
+ (VOID **) &MtrrValues
+ );
+ ASSERT_EFI_ERROR (Status);
+ ReadMtrrRegisters (MtrrValues);
+
+ WakeUpBuffer = AcpiCpuData->WakeUpBuffer;
+ ExchangeInfo = (MP_CPU_EXCHANGE_INFO *) (UINTN) (WakeUpBuffer + (0x1000 - 0x200));
+ ExchangeInfo->WakeupCount = (UINT32) 0;
+ ExchangeInfo->FinishedCount = (UINT32) 0;
+ ExchangeInfo->SerializeLock = (UINT32) 0;
+
+ //
+ // Restore features for BSP
+ //
+ InitializeFeaturesLog ((MP_CPU_S3_SCRIPT_DATA *) CpuS3DataPtr->S3BootScriptTable);
+
+ //
+ // Restore AP configuration
+ //
+ S3WakeUpAps ((CONST EFI_PEI_SERVICES **)PeiServices, AcpiCpuData, MtrrValues, MPRendezvousProcedure);
+
+ //
+ // Program XApic register
+ //
+ ProgramXApic (
+ TRUE
+ );
+
+ InterlockedIncrement (&(ExchangeInfo->SerializeLock));
+ while (ExchangeInfo->SerializeLock < AcpiCpuData->NumberOfCpus) {
+ CpuPause ();
+ }
+
+ Status = GetConfigBlock ((CONFIG_BLOCK_TABLE_HEADER *) ExchangeInfo->SiCpuPolicyPpi, &gCpuConfigGuid , (VOID *) &CpuConfig);
+ ASSERT_EFI_ERROR (Status);
+
+ DEBUG ((DEBUG_INFO, "Initialize Microcode Start \n"));
+ PostCode (0xC49);
+ InitializeMicrocode (
+ ExchangeInfo,
+ (CPU_MICROCODE_HEADER *) (UINTN) CpuConfig->MicrocodePatchAddress,
+ &FailedRevision
+ );
+
+ DEBUG ((DEBUG_INFO, "BuildGuid Data Hob Start \n"));
+ PostCode (0xC4D);
+ //
+ // Save acpi cpu data into one hob, it will be used by a callback when End of Pei Signal installed.
+ //
+ Hob = BuildGuidDataHob (
+ &gPeiAcpiCpuDataGuid,
+ (VOID *) (UINTN) AcpiCpuData,
+ (UINTN) sizeof (ACPI_CPU_DATA)
+ );
+ ASSERT (Hob != NULL);
+ DEBUG ((DEBUG_INFO, "CPU S3: Register notification to be trigerred at End of Pei event\n"));
+ Status = PeiServicesNotifyPpi (&mCpuS3ResumeNotifyDesc);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Wait for all APs to complete
+ //
+ while (ExchangeInfo->FinishedCount < AcpiCpuData->NumberOfCpus - 1) {
+ CpuPause ();
+ }
+
+ DEBUG ((DEBUG_INFO, "S3InitializeCpu Done \n"));
+ PostCode (0xC5F);
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ This function handles CPU S3 resume task at the end of PEI
+
+ @param[in] PeiServices Pointer to PEI Services Table.
+ @param[in] NotifyDesc Pointer to the descriptor for the Notification event that
+ caused this function to execute.
+ @param[in] Ppi Pointer to the PPI data associated with this function.
+
+ @retval EFI_STATUS Always return EFI_SUCCESS
+
+**/
+STATIC
+EFI_STATUS
+CpuS3ResumeAtEndOfPei (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDesc,
+ IN VOID *Ppi
+ )
+{
+ ACPI_CPU_DATA *AcpiCpuData;
+ EFI_PHYSICAL_ADDRESS WakeUpBuffer;
+ MP_CPU_S3_DATA_POINTER *CpuS3DataPtr;
+ MP_CPU_EXCHANGE_INFO *ExchangeInfo;
+ VOID *Hob;
+
+ DEBUG ((DEBUG_INFO, "Cpu S3 callback Entry\n"));
+
+ PostCode (0xC51);
+
+ //
+ // Find the saved acpi cpu data from HOB.
+ //
+ AcpiCpuData = NULL;
+ Hob = GetFirstGuidHob (&gPeiAcpiCpuDataGuid);
+ if (Hob != NULL) {
+ AcpiCpuData = (ACPI_CPU_DATA *) ((UINTN) Hob + sizeof (EFI_HOB_GUID_TYPE));
+ ASSERT (AcpiCpuData != NULL);
+ if (AcpiCpuData == NULL) {
+ return EFI_UNSUPPORTED;
+ }
+ } else {
+ return EFI_UNSUPPORTED;
+ }
+
+ WakeUpBuffer = AcpiCpuData->WakeUpBuffer;
+ ExchangeInfo = (MP_CPU_EXCHANGE_INFO *) (UINTN) (WakeUpBuffer + (0x1000 - 0x200));
+
+ //
+ // Have APs to continue the task - Restore S3BspMtrrTable
+ //
+ ExchangeInfo->WakeupCount = (UINT32) 0;
+ ExchangeInfo->FinishedCount = (UINT32) 0;
+
+ //
+ // Set MTRR to the final values
+ // Do not do it too early so as to avoid performance penalty
+ //
+ CpuS3DataPtr = (MP_CPU_S3_DATA_POINTER *) (UINTN) AcpiCpuData->CpuPrivateData;
+
+#ifdef EFI_DEBUG
+ ShowMtrrRegisters ((EFI_MTRR_VALUES *) CpuS3DataPtr->S3BspMtrrTable);
+#endif
+
+ SetMtrrRegisters ((EFI_MTRR_VALUES *) CpuS3DataPtr->S3BspMtrrTable);
+
+ MicroSecondDelay (1 * STALL_ONE_MILLI_SECOND); //< 1ms
+
+ while (ExchangeInfo->FinishedCount < AcpiCpuData->NumberOfCpus - 1) {
+ CpuPause ();
+ }
+ PostCode (0xC54);
+
+ return EFI_SUCCESS;
+}
+
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiCpuS3Lib/Ia32/MpEqu.h b/Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiCpuS3Lib/Ia32/MpEqu.h
new file mode 100644
index 0000000000..d8ec879d1e
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiCpuS3Lib/Ia32/MpEqu.h
@@ -0,0 +1,45 @@
+/** @file
+ This is the equates file for HT (Hyper-threading) support.
+
+ Copyright (c) 1999 - 2016, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#define VacantFlag 0x00
+#define NotVacantFlag 0xff
+
+#define LockLocation (0x1000 - 0x0200)
+#define StackStartAddressLocation (LockLocation + 0x04)
+#define StackSizeLocation (LockLocation + 0x08)
+#define CProcedureLocation (LockLocation + 0x0C)
+#define GdtrLocation (LockLocation + 0x10)
+#define IdtrLocation (LockLocation + 0x16)
+#define BufferStartLocation (LockLocation + 0x1C)
+#define PmodeOffsetLocation (LockLocation + 0x20)
+#define AcpiCpuDataAddressLocation (LockLocation + 0x24)
+#define MtrrValuesAddressLocation (LockLocation + 0x28)
+#define FinishedCountAddressLocation (LockLocation + 0x2C)
+#define WakeupCountAddressLocation (LockLocation + 0x30)
+#define SerializeLockAddressLocation (LockLocation + 0x34)
+#define MicrocodeAddressLocation (LockLocation + 0x38)
+#define BootScriptAddressLocation (LockLocation + 0x3C)
+#define StartStateLocation (LockLocation + 0x40)
+#define VirtualWireMode (LockLocation + 0x44)
+#define SemaphoreCheck (LockLocation + 0x48)
+#define PeiServices (LockLocation + 0x4C)
+#define PeiStall (LockLocation + 0x50)
+#define CpuPerfCtrlValue (LockLocation + 0x54)
+#define SiCpuPolicyPpi (LockLocation + 0x5C)
+#define MpSystemDataAddressLocation (LockLocation + 0x64)
+#define MpServicePpiAddressLocation (LockLocation + 0x68)
+#define CArgumentLocation (LockLocation + 0x6C)
+#define BistBufferLocation (LockLocation + 0x70)
+
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiCpuS3Lib/Ia32/MpEqu.inc b/Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiCpuS3Lib/Ia32/MpEqu.inc
new file mode 100644
index 0000000000..8fa3dc30a9
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiCpuS3Lib/Ia32/MpEqu.inc
@@ -0,0 +1,49 @@
+;; @file
+; This is the equates file used in MpFuncs.asm, for MP support.
+;
+; Copyright (c) 1999 - 2016, Intel Corporation. All rights reserved.<BR>
+;
+; This program and the accompanying materials
+; are licensed and made available under the terms and conditions of the BSD License
+; which accompanies this distribution. The full text of the license may be found at
+; http://opensource.org/licenses/bsd-license.php.
+;
+; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED
+;
+;;
+
+VacantFlag Equ 00h
+NotVacantFlag Equ 0ffh
+
+LockLocation equ 1000h - 0200h
+StackStartAddressLocation equ LockLocation + 04h
+StackSizeLocation equ LockLocation + 08h
+CProcedureLocation equ LockLocation + 0Ch
+GdtrLocation equ LockLocation + 10h
+IdtrLocation equ LockLocation + 16h
+BufferStartLocation equ LockLocation + 1Ch
+PmodeOffsetLocation equ LockLocation + 20h
+AcpiCpuDataAddressLocation equ LockLocation + 24h
+MtrrValuesAddressLocation equ LockLocation + 28h
+FinishedCountAddressLocation equ LockLocation + 2Ch
+WakeupCountAddressLocation equ LockLocation + 30h
+SerializeLockAddressLocation equ LockLocation + 34h
+MicrocodeAddressLocation equ LockLocation + 38h
+BootScriptAddressLocation equ LockLocation + 3Ch
+StartStateLocation equ LockLocation + 40h
+VirtualWireMode equ LockLocation + 44h
+SemaphoreCheck equ LockLocation + 48h
+PeiServices equ LockLocation + 4Ch
+PeiStall equ LockLocation + 50h
+CpuPerfCtrlValue equ LockLocation + 54h
+SiCpuPolicyPpi equ LockLocation + 5Ch
+MpSystemDataAddressLocation equ LockLocation + 64h
+MpServicePpiAddressLocation equ LockLocation + 68h
+CArgumentLocation equ LockLocation + 6Ch
+BistBufferLocation equ LockLocation + 70h
+
+PAUSE32 MACRO
+ DB 0F3h
+ DB 090h
+ ENDM
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiCpuS3Lib/Ia32/MpFuncs.S b/Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiCpuS3Lib/Ia32/MpFuncs.S
new file mode 100644
index 0000000000..8127ec30f8
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiCpuS3Lib/Ia32/MpFuncs.S
@@ -0,0 +1,210 @@
+## @file
+# This is the assembly code for MP support.
+#
+# Copyright (c) 1999 - 2016, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php.
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED
+#
+##
+
+#include "MpEqu.h"
+
+ .text
+ ASM_FUNCTION_REMOVE_IF_UNREFERENCED
+
+//-------------------------------------------------------------------------------------
+//S3RendezvousFunnelProc procedure follows. All APs execute their procedure. This
+//procedure serializes all the AP processors through an Init sequence. It must be
+//noted that APs arrive here very raw...ie: real mode, no stack.
+//ALSO THIS PROCEDURE IS EXECUTED BY APs ONLY ON 16 BIT MODE. HENCE THIS PROC
+//IS IN MACHINE CODE.
+//-------------------------------------------------------------------------------------
+//S3RendezvousFunnelProc (&WakeUpBuffer,MemAddress);
+
+.globl ASM_PFX(S3RendezvousFunnelProc)
+ASM_PFX(S3RendezvousFunnelProc):
+L_S3RendezvousFunnelProcStart:
+
+ .code16
+
+// At this point CS = 0x(vv00) and ip= 0x0.
+ mov %eax, %ebp
+ mov %cs, %ax
+ mov %ax, %ds
+ mov %ax, %es
+ mov %ax, %ss
+ xor %ax, %ax
+ mov %ax, %fs
+ mov %ax, %gs
+
+// Get APIC ID
+ mov $1, %eax
+ cpuid
+ shr $24, %ebx
+ and $0xff, %ebx // EBX is APIC ID
+
+// If it is the first time AP wakes up, just record AP's BIST
+// Otherwise, switch to protected mode.
+
+ mov $StartStateLocation, %si
+ cmpl $0, (%si)
+ jnz L_SkipRecordBist
+
+// Record BIST information
+//
+ mov $8, %al
+ mul %bl
+ mov $BistBufferLocation, %si
+ add %ax, %si
+
+ movl $1, (%si) // Set Valid Flag
+ mov %ebp, 4(%si) // Store BIST value
+
+L_SkipRecordBist:
+// Switch to flat mode.
+
+ mov $BufferStartLocation, %si
+ mov (%si), %ebx
+
+ mov $PmodeOffsetLocation, %di
+ mov (%di), %eax
+ mov %ax, %di
+ sub $6, %di
+ add %ebx, %eax
+ mov %eax, (%di)
+
+ mov $0, %esi
+ mov $GdtrLocation, %si
+ lgdtl %cs:(%esi)
+
+ xor %ax, %ax
+ mov %ax, %ds
+
+ mov %cr0, %eax
+ or $0x00000003, %eax
+ mov %eax, %cr0
+
+ .byte 0x66, 0x67, 0xea // far jump
+ .long 0x00 // 32-bit offset
+ .short 0x20 // 16-bit selector
+
+ .code32
+L_NemInit: // protected mode entry point
+ mov $0x18, %ax
+ mov %ax, %ds
+ mov %ax, %es
+ mov %ax, %fs
+ mov %ax, %gs
+ mov %ax, %ss
+
+ mov %ebx, %esi
+
+ mov %esi, %edi
+ add $StartStateLocation, %edi
+ mov $1, %eax
+ movl %eax, (%edi)
+
+ mov %esi, %edi
+ add $LockLocation, %edi
+ mov $NotVacantFlag, %eax
+L_TestLock:
+ xchg %eax, (%edi)
+ cmp $NotVacantFlag, %eax
+ jz L_TestLock
+
+L_ProgramStack:
+
+ mov %esi, %edi
+ add $StackSizeLocation, %edi
+ mov (%edi), %eax
+ mov %esi, %edi
+ add $StackStartAddressLocation, %edi
+ add (%edi), %eax
+ mov %eax, %esp
+ movl %eax, (%edi)
+
+L_Releaselock:
+
+ mov $VacantFlag, %eax
+ mov %esi, %edi
+ add $LockLocation, %edi
+ xchg %eax, (%edi)
+
+L_CProcedureInvoke:
+
+ mov %esi, %edi
+ add $CArgumentLocation, %edi
+ mov (%edi), %eax
+ push %eax
+
+ mov %esi, %edi
+ add $CProcedureLocation, %edi
+ mov (%edi), %eax
+
+ call *%eax
+ add $4, %esp
+
+L_InterlockedIncrementFinishedCount:
+ mov %esi, %edi
+ add $FinishedCountAddressLocation, %edi
+ lock incl (%edi)
+
+1:
+ cli
+
+ hlt
+ jmp 1b
+
+
+//-------------------------------------------------------------------------------------
+// S3SemaphoreStartAddress
+//-------------------------------------------------------------------------------------
+
+L_S3SemaphoreStartAddress:
+ push %ebp
+ mov %esp, %ebp
+ mov 0x8(%ebp), %eax
+1:
+ cmpl $0, (%eax)
+ jz 1f
+
+ pause
+ jmp 1b
+
+1:
+ pop %ebp
+ ret
+
+//-------------------------------------------------------------------------------
+// S3AsmGetAddressMap
+//-------------------------------------------------------------------------------------
+.set L_NemInitOffset, L_NemInit - L_S3RendezvousFunnelProcStart
+.set L_SemaphoreOffset, L_S3SemaphoreStartAddress - L_S3RendezvousFunnelProcStart
+
+.globl ASM_PFX(S3AsmGetAddressMap)
+ASM_PFX(S3AsmGetAddressMap):
+ mov $L_S3RendezvousFunnelProcStart, %eax
+ ret
+
+
+//-------------------------------------------------------------------------------
+// S3AsmGetPmodeOffset
+//-------------------------------------------------------------------------------------
+.globl ASM_PFX(S3AsmGetPmodeOffset)
+ASM_PFX(S3AsmGetPmodeOffset):
+ mov $L_NemInitOffset, %eax
+ ret
+
+//-------------------------------------------------------------------------------
+// S3AsmGetSemaphoreCheckOffset
+//-------------------------------------------------------------------------------------
+.globl ASM_PFX(S3AsmGetSemaphoreCheckOffset)
+ASM_PFX(S3AsmGetSemaphoreCheckOffset):
+ mov $L_SemaphoreOffset, %eax
+ ret \ No newline at end of file
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiCpuS3Lib/Ia32/MpFuncs.asm b/Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiCpuS3Lib/Ia32/MpFuncs.asm
new file mode 100644
index 0000000000..9e3450d0d3
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiCpuS3Lib/Ia32/MpFuncs.asm
@@ -0,0 +1,206 @@
+;; @file
+; This is the assembly code for MP support.
+;
+; Copyright (c) 2005 - 2016, Intel Corporation. All rights reserved.<BR>
+;
+; This program and the accompanying materials
+; are licensed and made available under the terms and conditions of the BSD License
+; which accompanies this distribution. The full text of the license may be found at
+; http://opensource.org/licenses/bsd-license.php.
+;
+; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED
+;
+;;
+
+include MpEqu.inc
+
+;-------------------------------------------------------------------------------------
+;S3RendezvousFunnelProc procedure follows. All APs execute their procedure. This
+;procedure serializes all the AP processors through an Init sequence. It must be
+;noted that APs arrive here very raw...ie: real mode, no stack.
+;ALSO THIS PROCEDURE IS EXECUTED BY APs ONLY ON 16 BIT MODE. HENCE THIS PROC
+;IS IN MACHINE CODE.
+;-------------------------------------------------------------------------------------
+;S3RendezvousFunnelProc (&WakeUpBuffer,MemAddress);
+
+.686p
+.model flat
+.code
+
+PAUSE32 MACRO
+ DB 0F3h
+ DB 090h
+ ENDM
+
+S3RendezvousFunnelProc PROC PUBLIC
+S3RendezvousFunnelProcStart::
+
+;Step-1: Grab a lock. At this point CS = 0x(vv00) and ip= 0x0.
+
+ db 8ch,0c8h ; mov ax,cs
+ db 8eh,0d8h ; mov ds,ax
+ db 8eh,0c0h ; mov es,ax
+ db 8eh,0d0h ; mov ss,ax
+ db 33h,0c0h ; xor ax,ax
+ db 8eh,0e0h ; mov fs,ax
+ db 8eh,0e8h ; mov gs,ax
+
+ db 0BEh ; opcode of mov si, mem16
+ dw BufferStartLocation ; mov si, BufferStartLocation
+ db 66h, 8Bh, 1Ch ; mov ebx,dword ptr [si]
+
+ db 0BFh ; opcode of mov di, mem16
+ dw PmodeOffsetLocation ; mov di, PmodeOffsetLocation
+ db 66h, 8Bh, 05h ; mov eax,dword ptr [di]
+ db 8Bh, 0F8h ; mov di, ax
+ db 83h, 0EFh,06h ; sub di, 06h
+ db 66h, 03h, 0C3h ; add eax, ebx
+ db 66h, 89h, 05h ; mov dword ptr [di],eax
+
+ db 0BEh ; opcode of mov si, mem16
+ dw GdtrLocation ; mov si, GdtrLocation
+ db 66h ; db 66h
+ db 2Eh, 0Fh, 01h, 14h ; lgdt fword ptr cs:[si]
+
+ db 0BEh ; opcode of mov si, mem16
+ dw IdtrLocation ; mov si, IdtrProfile
+ db 66h ; db 66h
+ db 2Eh, 0Fh, 01h, 1Ch ; lidt fword ptr cs:[si]
+
+ db 33h, 0C0h ; xor ax, ax
+ db 8Eh, 0D8h ; mov ds, ax
+
+ db 0Fh, 20h, 0C0h ; mov eax, cr0 ;Get control register 0
+ db 66h, 83h, 0C8h, 03h ; or eax, 000000003h ;Set PE bit (bit #0) & MP
+ db 0Fh, 22h, 0C0h ; mov cr0, eax
+
+ db 66h, 67h, 0EAh ; far jump
+ dd 0h ; 32-bit offset
+ dw 20h ; 16-bit selector
+
+NemInit:: ; protected mode entry point
+
+ db 66h, 0B8h, 18h, 00h ; mov ax, 18h
+ db 66h, 8Eh, 0D8h ; mov ds, ax
+ db 66h, 8Eh, 0C0h ; mov es, ax
+ db 66h, 8Eh, 0E0h ; mov fs, ax
+ db 66h, 8Eh, 0E8h ; mov gs, ax
+ db 66h, 8Eh, 0D0h ; mov ss, ax ; Flat mode setup.
+
+ mov esi, ebx
+
+ mov edi, esi
+ add edi, StartStateLocation
+ mov eax, 1
+ mov dword ptr [edi], eax
+
+ mov edi, esi
+ add edi, LockLocation
+ mov eax, NotVacantFlag
+TestLock::
+ xchg dword ptr [edi], eax
+ cmp eax, NotVacantFlag
+ jz TestLock
+
+ProgramStack::
+
+ mov edi, esi
+ add edi, StackSizeLocation
+ mov eax, dword ptr [edi]
+ mov edi, esi
+ add edi, StackStartAddressLocation
+ add eax, dword ptr [edi]
+ mov esp, eax
+ mov dword ptr [edi], eax
+
+Releaselock::
+
+ mov eax, VacantFlag
+ mov edi, esi
+ add edi, LockLocation
+ xchg dword ptr [edi], eax
+
+CProcedureInvoke::
+
+ mov edi, esi
+ add edi, MtrrValuesAddressLocation
+ mov eax, dword ptr [edi]
+ push eax
+
+ mov eax, esi
+ add eax, LockLocation
+ push eax
+
+ mov edi, esi
+ add edi, CProcedureLocation
+ mov eax, dword ptr [edi]
+
+;
+; itp.threads[n].msr(0x121, 0x2FBA2E2500010408)
+; WA for ACPI PM1 timer BXT 0 and 1
+;
+ push ecx
+ push eax
+ push edx
+
+ mov ecx, 0121h
+ rdmsr
+ test eax, eax
+ jnz SkipAcpiTimerWA
+ mov eax, 00010408h ; Bit 16 is enable and 15:0 address
+ mov edx, 2FBA2E25h
+ wrmsr
+SkipAcpiTimerWA:
+ pop edx
+ pop eax
+ pop ecx
+
+ call eax
+ add esp, 8
+
+ cli
+ hlt
+ jmp $-2
+
+S3RendezvousFunnelProc ENDP
+
+S3SemaphoreStartAddress PROC C, SemaphoreAddress:PTR DWORD
+ mov eax, SemaphoreAddress
+@@:
+ cmp dword ptr [eax], 0
+ jz @F
+
+ PAUSE32
+ jmp @B
+@@:
+ ret
+S3SemaphoreStartAddress ENDP
+
+S3RendezvousFunnelProcEnd::
+
+
+;-------------------------------------------------------------------------------------
+; S3AsmGetAddressMap (&AddressMap);
+;-------------------------------------------------------------------------------------
+S3AsmGetAddressMap PROC near C PUBLIC
+
+ mov eax, S3RendezvousFunnelProcStart
+ ret
+
+S3AsmGetAddressMap ENDP
+
+S3AsmGetPmodeOffset PROC near C PUBLIC
+
+ mov eax, NemInit - S3RendezvousFunnelProcStart
+ ret
+
+S3AsmGetPmodeOffset ENDP
+
+S3AsmGetSemaphoreCheckOffset PROC near C PUBLIC
+ mov eax, S3SemaphoreStartAddress - S3RendezvousFunnelProcStart
+ ret
+S3AsmGetSemaphoreCheckOffset ENDP
+
+END
+
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiCpuS3Lib/PeiCpuS3Lib.inf b/Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiCpuS3Lib/PeiCpuS3Lib.inf
new file mode 100644
index 0000000000..749dd98ad7
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiCpuS3Lib/PeiCpuS3Lib.inf
@@ -0,0 +1,59 @@
+## @file
+# Component information file for CPU S3 module.
+#
+# Copyright (c) 2014 - 2016, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php.
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010017
+ BASE_NAME = PeiCpuS3Lib
+ FILE_GUID = 6351F303-B76A-44F9-9171-026BDDCA8654
+ VERSION_STRING = 1.0
+ MODULE_TYPE = PEIM
+ LIBRARY_CLASS = CpuS3Lib
+
+[LibraryClasses]
+ CpuPlatformLib
+ DebugLib
+ BaseLib
+ PeiServicesLib
+ BaseMemoryLib
+ SynchronizationLib
+ HobLib
+ ReportStatusCodeLib
+ MemoryAllocationLib
+ IoLib
+ TimerLib
+ CpuCommonLib
+ PostCodeLib
+ MpServiceLib
+
+[Packages]
+ MdePkg/MdePkg.dec
+ BroxtonSiPkg/BroxtonSiPkg.dec
+ BroxtonSiPkg/BroxtonSiPrivate.dec
+
+[Sources]
+ CpuS3Lib.c
+
+[Sources.IA32]
+ Ia32/MpFuncs.S | GCC
+ Ia32/MpFuncs.asm | MSFT
+
+[Ppis]
+ gSiCpuPolicyPpiGuid ## CONSUMES
+ gPeiSmmAccessPpiGuid ## CONSUMES
+ gEfiEndOfPeiSignalPpiGuid ## NOTIFY
+
+[Guids]
+ gSmramCpuDataHeaderGuid ## UNDEFINED
+ gPeiAcpiCpuDataGuid ## UNDEFINED