summaryrefslogtreecommitdiff
path: root/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit
diff options
context:
space:
mode:
authorGuo Mang <mang.guo@intel.com>2016-08-03 11:46:45 +0800
committerGuo Mang <mang.guo@intel.com>2016-08-04 10:33:10 +0800
commit9dfd62064d1d1a6344165febb44c7b0d0f3a6a1e (patch)
treee6734a38a607f96255aff50d13b92809779ff737 /BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit
parent177e76bd8e9a863b4bd06a95f0e7cb5e4851812f (diff)
downloadedk2-platforms-9dfd62064d1d1a6344165febb44c7b0d0f3a6a1e.tar.xz
BraswellPlatformPkg: Move IntelSiliconBasic to Common/Silicon/IntelSiliconBasic
Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Guo Mang <mang.guo@intel.com> Reviewed-by: David Wei <david.wei@intel.com>
Diffstat (limited to 'BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit')
-rw-r--r--BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/Cpu.c999
-rw-r--r--BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/CpuDataStruct.h121
-rw-r--r--BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/CpuDxe.h240
-rw-r--r--BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/CpuRegs.h410
-rw-r--r--BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/Exception.h71
-rw-r--r--BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/Ia32/CpuAsm.asm693
-rw-r--r--BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/Ia32/CpuAsm.s761
-rw-r--r--BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/Ia32/Exception.c337
-rw-r--r--BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/Ia32/Htequ.inc40
-rw-r--r--BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/Ia32/InitializeFpu.s72
-rw-r--r--BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/Ia32/MPFuncs32.asm426
-rw-r--r--BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/Ia32/MPFuncs32.s444
-rw-r--r--BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/Ia32/MemoryOperation.c380
-rw-r--r--BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/Ia32/MpCommon32.asm103
-rw-r--r--BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/Ia32/MpCommon32.s114
-rw-r--r--BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/Ia32/MpCpu.c90
-rw-r--r--BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/Ia32/MpProc.asm83
-rw-r--r--BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/Ia32/MpProc.s69
-rw-r--r--BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/Ia32/ProcessorDef.h56
-rw-r--r--BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/MemoryAttribute.c975
-rw-r--r--BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/MemoryAttribute.h136
-rw-r--r--BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/Microcode.c483
-rw-r--r--BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/MiscFuncs.c103
-rw-r--r--BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/MiscFuncs.h45
-rw-r--r--BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/MpCommon.c879
-rw-r--r--BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/MpCommon.h425
-rw-r--r--BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/MpCpu.inf143
-rw-r--r--BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/MpService.c1781
-rw-r--r--BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/MtrrSync.c233
-rw-r--r--BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/PlatformMpService.h636
-rw-r--r--BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/x64/Cpu.asm199
-rw-r--r--BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/x64/CpuAsm.asm462
-rw-r--r--BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/x64/CpuInitDxeGccDummy.c184
-rw-r--r--BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/x64/Exception.c319
-rw-r--r--BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/x64/Htequ.inc44
-rw-r--r--BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/x64/MemoryOperation.c718
-rw-r--r--BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/x64/MpCpu.c76
-rw-r--r--BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/x64/MpFuncs.asm604
-rw-r--r--BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/x64/PlatformCpuLib.h135
-rw-r--r--BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/x64/ProcessorDef.h57
-rw-r--r--BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/x64/VirtualMemory.h147
41 files changed, 14293 insertions, 0 deletions
diff --git a/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/Cpu.c b/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/Cpu.c
new file mode 100644
index 0000000000..e8ef367545
--- /dev/null
+++ b/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/Cpu.c
@@ -0,0 +1,999 @@
+/** @file
+ Cpu driver, which initializes CPU and implements CPU Architecture
+ Protocol as defined in Framework specification.
+
+ Copyright (c) 1999 - 2015, 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 "CpuDxe.h"
+#include "Exception.h"
+#include "MiscFuncs.h"
+#include "MemoryAttribute.h"
+#include <Library/IoLib.h>
+#include <Library/PcdLib.h>
+
+#define SAMPLE_TICK_COUNT 100
+
+extern UINT64 mValidMtrrAddressMask;
+extern UINT64 mValidMtrrBitsMask;
+extern EFI_CPU_MICROCODE_HEADER **mMicrocodePointerBuffer;
+
+VOID *mSmmBaseRegistration;
+EFI_METRONOME_ARCH_PROTOCOL *mMetronome;
+BOOLEAN mIsFlushingGCD = TRUE;
+UINT64 mCpuFrequency = 0;
+
+
+CONST UINT16 miFSBFrequencyTable[] = {
+ 83, // 83.4MHz
+ 100, // 100MHz
+ 133, // 133.4MHz
+ 116, // 116.5MHz
+ 83, // 83.3MHz
+ 100, // 100MHz
+ 133, // 133.3MHz
+ 116, // 116.7MHz
+
+ 80, // 80MHz
+ 93, // 93.3MHz
+ 90, // 90MHz
+ 88, // 88.9MHz
+ 87 // 87.5MHz
+};
+
+//
+// Function declarations
+//
+EFI_STATUS
+EFIAPI
+InitializeCpu (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+EFI_STATUS
+PrepareMemory (
+ VOID
+ );
+
+EFI_STATUS
+EFIAPI
+FlushCpuDataCache (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN EFI_PHYSICAL_ADDRESS Start,
+ IN UINT64 Length,
+ IN EFI_CPU_FLUSH_TYPE FlushType
+ );
+
+EFI_STATUS
+EFIAPI
+EnableInterrupt (
+ IN EFI_CPU_ARCH_PROTOCOL *This
+ );
+
+EFI_STATUS
+EFIAPI
+DisableInterrupt (
+ IN EFI_CPU_ARCH_PROTOCOL *This
+ );
+
+EFI_STATUS
+EFIAPI
+CpuGetInterruptState (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ OUT BOOLEAN *State
+ );
+
+EFI_STATUS
+EFIAPI
+Init (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN EFI_CPU_INIT_TYPE InitType
+ );
+
+EFI_STATUS
+EFIAPI
+RegisterInterruptHandler (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN EFI_EXCEPTION_TYPE InterruptType,
+ IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler
+ );
+
+EFI_STATUS
+EFIAPI
+GetTimerValue (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN UINT32 TimerIndex,
+ OUT UINT64 *TimerValue,
+ OUT UINT64 *TimerPeriod OPTIONAL
+ );
+
+EFI_STATUS
+EFIAPI
+SetMemoryAttributes (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length,
+ IN UINT64 Attributes
+ );
+
+//
+// Global Variables
+//
+EFI_CPU_INTERRUPT_HANDLER mExternalVectorTable[0x100];
+
+BOOLEAN mInterruptState = FALSE;
+
+//
+// The Cpu Architectural Protocol that this Driver produces
+//
+EFI_CPU_ARCH_PROTOCOL gCpu = {
+ FlushCpuDataCache,
+ EnableInterrupt,
+ DisableInterrupt,
+ CpuGetInterruptState,
+ Init,
+ RegisterInterruptHandler,
+ GetTimerValue,
+ SetMemoryAttributes,
+ 1, // NumberOfTimers
+ 4, // DmaBufferAlignment
+};
+
+/**
+ Flush CPU data cache. If the instruction cache is fully coherent
+ with all DMA operations then function can just return EFI_SUCCESS.
+
+ @param[in] This Protocol instance structure
+ @param[in] Start Physical address to start flushing from.
+ @param[in] Length Number of bytes to flush. Round up to chipset granularity.
+ @param[in] FlushType Specifies the type of flush operation to perform.
+
+ @retval EFI_SUCCESS If cache was flushed
+ @retval EFI_UNSUPPORTED If flush type is not supported.
+ @retval EFI_DEVICE_ERROR If requested range could not be flushed.
+
+**/
+EFI_STATUS
+EFIAPI
+FlushCpuDataCache (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN EFI_PHYSICAL_ADDRESS Start,
+ IN UINT64 Length,
+ IN EFI_CPU_FLUSH_TYPE FlushType
+ )
+{
+ if (FlushType == EfiCpuFlushTypeWriteBackInvalidate) {
+ AsmWbinvd ();
+ return EFI_SUCCESS;
+ } else if (FlushType == EfiCpuFlushTypeInvalidate) {
+ AsmInvd ();
+ return EFI_SUCCESS;
+ } else {
+ return EFI_UNSUPPORTED;
+ }
+}
+
+/**
+ Enables CPU interrupts.
+
+ @param[in] This Protocol instance structure
+
+ @retval EFI_SUCCESS If interrupts were enabled in the CPU
+ @retval EFI_DEVICE_ERROR If interrupts could not be enabled on the CPU.
+
+**/
+EFI_STATUS
+EFIAPI
+EnableInterrupt (
+ IN EFI_CPU_ARCH_PROTOCOL *This
+ )
+{
+ CpuEnableInterrupt ();
+ mInterruptState = TRUE;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Disables CPU interrupts.
+
+ @param[in] This Protocol instance structure
+
+ @retval EFI_SUCCESS If interrupts were disabled in the CPU.
+ @retval EFI_DEVICE_ERROR If interrupts could not be disabled on the CPU.
+
+**/
+EFI_STATUS
+EFIAPI
+DisableInterrupt (
+ IN EFI_CPU_ARCH_PROTOCOL *This
+ )
+{
+ CpuDisableInterrupt ();
+ mInterruptState = FALSE;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Return the state of interrupts.
+
+ @param[in] This Protocol instance structure
+ @param[out] State Pointer to the CPU's current interrupt state
+
+ @retval EFI_SUCCESS If interrupts were disabled in the CPU.
+ @retval EFI_INVALID_PARAMETER State is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+CpuGetInterruptState (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ OUT BOOLEAN *State
+ )
+{
+ if (State == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *State = mInterruptState;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Generates an INIT to the CPU
+
+ @param[in] This Protocol instance structure
+ @param[in] InitType Type of CPU INIT to perform
+
+ @retval EFI_SUCCESS If CPU INIT occurred. This value should never be seen.
+ @retval EFI_DEVICE_ERROR If CPU INIT failed.
+ @retval EFI_UNSUPPORTED Requested type of CPU INIT not supported.
+
+**/
+EFI_STATUS
+EFIAPI
+Init (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN EFI_CPU_INIT_TYPE InitType
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ Registers a function to be called from the CPU interrupt handler.
+
+ @param[in] This Protocol instance structure
+ @param[in] InterruptType Defines which interrupt to hook. IA-32 valid range
+ is 0x00 through 0xFF
+ @param[in] InterruptHandler A pointer to a function of type
+ EFI_CPU_INTERRUPT_HANDLER that is called when a
+ processor interrupt occurs. A null pointer
+ is an error condition.
+
+ @retval EFI_SUCCESS If handler installed or uninstalled.
+
+ @retval EFI_ALREADY_STARTED InterruptHandler is not NULL, and a handler for
+ InterruptType was previously installed
+
+ @retval EFI_INVALID_PARAMETER InterruptHandler is NULL, and a handler for
+ InterruptType was not previously installed.
+
+ @retval EFI_UNSUPPORTED The interrupt specified by InterruptType is not
+ supported.
+
+**/
+EFI_STATUS
+EFIAPI
+RegisterInterruptHandler (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN EFI_EXCEPTION_TYPE InterruptType,
+ IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler
+ )
+{
+ if (InterruptType < 0 || InterruptType > 0xff) {
+ return EFI_UNSUPPORTED;
+ }
+
+ if (InterruptHandler == NULL && mExternalVectorTable[InterruptType] == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (InterruptHandler != NULL && mExternalVectorTable[InterruptType] != NULL) {
+ return EFI_ALREADY_STARTED;
+ }
+
+ mExternalVectorTable[InterruptType] = InterruptHandler;
+ return EFI_SUCCESS;
+}
+
+/**
+ Returns the CPU core to processor bus frequency ratio.
+
+ @param[out] Ratio Pointer to the CPU core to processor bus frequency ratio.
+
+ @retval EFI_SUCCESS If the ratio is returned successfully
+ @retval EFI_UNSUPPORTED If the ratio cannot be measured
+ @retval EFI_INVALID_PARAMETER If the input parameter is not valid
+
+**/
+EFI_STATUS
+GetCpuBusRatio (
+ OUT UINT32 *Ratio
+ )
+{
+ UINT64 TempQword;
+
+ if (Ratio == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ TempQword = AsmReadMsr64 (EFI_MSR_IA32_PERF_STS);
+ *Ratio = (UINT32) (RShiftU64 (TempQword, 8) & 0x1F);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Returns a timer value from one of the CPU's internal timers. There is no
+ inherent time interval between ticks but is a function of the CPU frequency.
+
+ @param[in] This Protocol instance structure.
+ @param[in] TimerIndex Specifies which CPU timer is requested.
+ @param[out] TimerValue Pointer to the returned timer value.
+ @param[out] TimerPeriod A pointer to the amount of time that passes in femtoseconds (10-15) for each
+ increment of TimerValue. If TimerValue does not increment at a predictable
+ rate, then 0 is returned. The amount of time that has passed between two calls to
+ GetTimerValue() can be calculated with the formula
+ (TimerValue2 - TimerValue1) * TimerPeriod. This parameter is optional and may be NULL.
+
+ @retval EFI_SUCCESS If the CPU timer count was returned.
+ @retval EFI_UNSUPPORTED If the CPU does not have any readable timers.
+ @retval EFI_DEVICE_ERROR If an error occurred while reading the timer.
+ @retval EFI_INVALID_PARAMETER TimerIndex is not valid or TimerValue is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+GetTimerValue (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN UINT32 TimerIndex,
+ OUT UINT64 *TimerValue,
+ OUT UINT64 *TimerPeriod OPTIONAL
+ )
+{
+ UINT64 Actual;
+
+ if (TimerValue == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (TimerIndex != 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *TimerValue = AsmReadTsc ();
+
+ if (TimerPeriod != NULL) {
+ GetActualFrequency (mMetronome, &Actual);
+ *TimerPeriod = DivU64x32 (1000000000, (UINT32) Actual);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Set memory cacheability attributes for given range of memeory
+
+ @param[in] This Protocol instance structure
+ @param[in] BaseAddress Specifies the start address of the memory range
+ @param[in] Length Specifies the length of the memory range
+ @param[in] Attributes The memory cacheability for the memory range
+
+ @retval
+
+ EFI_SUCCESS If the cacheability of that memory range is set successfully
+ EFI_UNSUPPORTED If the desired operation cannot be done
+ EFI_INVALID_PARAMETER The input parameter is not correct, such as Length = 0
+
+**/
+EFI_STATUS
+EFIAPI
+SetMemoryAttributes (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length,
+ IN UINT64 Attributes
+ )
+{
+ EFI_STATUS Status;
+ UINT64 TempQword;
+ UINT32 MsrNum, MsrNumEnd;
+ UINTN MtrrNumber;
+ BOOLEAN Positive;
+ BOOLEAN OverLap;
+ UINTN Remainder;
+ EFI_MP_SERVICES_PROTOCOL *MpService;
+ EFI_STATUS Status1;
+
+ if (mIsFlushingGCD) {
+ return EFI_SUCCESS;
+ }
+
+ TempQword = 0;
+
+ //
+ // Check for invalid parameter
+ //
+ if (Length == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((BaseAddress &~mValidMtrrAddressMask) != 0 || (Length &~mValidMtrrAddressMask) != 0) {
+ return EFI_UNSUPPORTED;
+ }
+
+ switch (Attributes) {
+ case EFI_MEMORY_UC:
+ Attributes = EFI_CACHE_UNCACHEABLE;
+ break;
+
+ case EFI_MEMORY_WC:
+ Attributes = EFI_CACHE_WRITECOMBINING;
+ break;
+
+ case EFI_MEMORY_WT:
+ Attributes = EFI_CACHE_WRITETHROUGH;
+ break;
+
+ case EFI_MEMORY_WP:
+ Attributes = EFI_CACHE_WRITEPROTECTED;
+ break;
+
+ case EFI_MEMORY_WB:
+ Attributes = EFI_CACHE_WRITEBACK;
+ break;
+
+ default:
+ return EFI_UNSUPPORTED;
+ }
+ //
+ // Check if Fixed MTRR
+ //
+ Status = EFI_SUCCESS;
+ while ((BaseAddress < (1 << 20)) && (Length > 0) && Status == EFI_SUCCESS) {
+ PreMtrrChange ();
+ Status = ProgramFixedMtrr (Attributes, &BaseAddress, &Length);
+ PostMtrrChange ();
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ if (Length == 0) {
+ //
+ // Just Fixed MTRR. NO need to go through Variable MTRR
+ //
+ goto Done;
+ }
+
+ //
+ // since mem below 1m will be override by fixed mtrr, we can set it to 0 to save mtrr.
+ //
+ if (BaseAddress == 0x100000) {
+ BaseAddress = 0;
+ Length += 0x100000;
+ }
+
+ //
+ // Check memory base address alignment
+ //
+ Remainder = ModU64x32(BaseAddress, (UINT32) Power2MaxMemory (LShiftU64 (Length, 1)));
+ if (Remainder != 0) {
+ Remainder = ModU64x32 (BaseAddress, (UINT32) Power2MaxMemory (Length));
+ if (Remainder != 0) {
+ Status = EFI_UNSUPPORTED;
+ goto Done;
+ }
+ }
+
+ //
+ // Check overlap
+ //
+ GetMemoryAttribute ();
+ OverLap = CheckMemoryAttributeOverlap (BaseAddress, BaseAddress + Length - 1);
+ if (OverLap) {
+ Status = CombineMemoryAttribute (Attributes, &BaseAddress, &Length);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ if (Length == 0) {
+ //
+ // combine successfully
+ //
+ Status = EFI_SUCCESS;
+ goto Done;
+ }
+ } else {
+ if (Attributes == EFI_CACHE_UNCACHEABLE) {
+ Status = EFI_SUCCESS;
+ goto Done;
+ }
+ }
+
+ //
+ // Program Variable MTRRs
+ //
+ if (mUsedMtrr >= 6) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ //
+ // Find first unused MTRR
+ //
+ MsrNumEnd = EFI_MSR_CACHE_VARIABLE_MTRR_BASE + (2 * (UINT32)(AsmReadMsr64(EFI_MSR_IA32_MTRR_CAP) & B_EFI_MSR_IA32_MTRR_CAP_VARIABLE_SUPPORT));
+ for (MsrNum = EFI_MSR_CACHE_VARIABLE_MTRR_BASE; MsrNum < MsrNumEnd; MsrNum += 2) {
+ if ((AsmReadMsr64 (MsrNum + 1) & B_EFI_MSR_CACHE_MTRR_VALID) == 0) {
+ break;
+ }
+ }
+
+ TempQword = Length;
+
+ if (TempQword == Power2MaxMemory (TempQword)) {
+ ProgramVariableMtrr (
+ MsrNum,
+ BaseAddress,
+ Length,
+ Attributes
+ );
+ } else {
+
+ GetDirection (TempQword, &MtrrNumber, &Positive);
+
+ if ((mUsedMtrr + MtrrNumber) > 6) {
+ goto Done;
+ }
+
+ if (!Positive) {
+ Length = Power2MaxMemory (LShiftU64 (TempQword, 1));
+ ProgramVariableMtrr (
+ MsrNum,
+ BaseAddress,
+ Length,
+ Attributes
+ );
+ BaseAddress += TempQword;
+ TempQword = Length - TempQword;
+ Attributes = EFI_CACHE_UNCACHEABLE;
+ }
+
+ do {
+ //
+ // Find unused MTRR
+ //
+ for (; MsrNum < MsrNumEnd; MsrNum += 2) {
+ if ((AsmReadMsr64 (MsrNum + 1) & B_EFI_MSR_CACHE_MTRR_VALID) == 0) {
+ break;
+ }
+ }
+
+ Length = Power2MaxMemory (TempQword);
+ ProgramVariableMtrr (
+ MsrNum,
+ BaseAddress,
+ Length,
+ Attributes
+ );
+ BaseAddress += Length;
+ TempQword -= Length;
+
+ } while (TempQword);
+
+ }
+
+Done:
+ Status1 = gBS->LocateProtocol (
+ &gEfiMpServiceProtocolGuid,
+ NULL,
+ (VOID **) &MpService
+ );
+ if (!EFI_ERROR (Status1)) {
+ ReadMtrrRegisters ();
+ Status1 = MpService->StartupAllAPs (
+ MpService,
+ MpMtrrSynchUp,
+ TRUE,
+ NULL,
+ 0,
+ NULL,
+ NULL
+ );
+ }
+
+ return Status;
+}
+
+/**
+ @todo Add structure description
+
+**/
+typedef struct {
+ UINT8 Bus;
+ UINT8 Device;
+ UINT8 Function;
+} PCI_CONTROLLER_BITMAP;
+
+PCI_CONTROLLER_BITMAP mHostBus[] =
+{
+ {0, 0, 0},
+ {0, 27, 0},
+ {0, 30, 0},
+ {0, 30, 1},
+ {0, 30, 2},
+ {0, 30, 3},
+ {0, 30, 4},
+ {0, 30, 5},
+ {0, 30, 6},
+ {0, 30, 7},
+ {0, 31, 3},
+ {0, 16, 0},
+ {0, 17, 0},
+ {0, 18, 0},
+ {0, 26, 0},
+ {0, 26, 1},
+ {0, 31, 0},
+ {0, 21, 0} ,
+ {0, 19, 0} ,
+ {0, 2, 0},
+ {0, 29, 0},
+ {0, 20, 0} ,
+ {0, 22, 0},
+ {0, 3, 0},
+ {0, 24, 0},
+ {0, 24, 1} ,
+ {0, 24, 2},
+ {0, 24, 3} ,
+ {0, 24, 4},
+ {0, 24, 5},
+ {0, 24, 6} ,
+ {0, 24, 7} ,
+ {0, 28, 0},
+ {0, 28, 1} ,
+ {0, 28, 2},
+ {0, 28, 3} ,
+ {0, 23, 0},
+ {0, 25, 0} ,
+};
+
+/**
+ Initialize the state information for the CPU Architectural Protocol
+
+ @param[in] ImageHandle Image handle of the loaded driver
+ @param[in] SystemTable Pointer to the System Table
+
+ @retval
+
+ EFI_SUCCESS Thread can be successfully created
+ EFI_OUT_OF_RESOURCES Cannot allocate protocol data structure
+ EFI_DEVICE_ERROR Cannot create the thread
+
+**/
+EFI_STATUS
+EFIAPI
+InitializeCpu (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE NewHandle;
+ EFI_EVENT LegacyBootEvent;
+ EFI_EVENT EndOfDxeEvent = NULL;
+
+ //
+ // DXE CPU Post Codes are defined in PostCode.c, variable mPort80Table[]
+ //
+ Status = REPORT_STATUS_CODE_EX (
+ EFI_PROGRESS_CODE,
+ EFI_COMPUTING_UNIT_HOST_PROCESSOR | EFI_CU_HP_PC_DXE_INIT,
+ 0,
+ &gEfiCallerIdGuid,
+ NULL,
+ NULL,
+ 0
+ );
+
+ //
+ // Initialize the Global Descriptor Table
+ //
+ InitializeSelectors ();
+
+ Status = PrepareMemory ();
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Initialize Exception Handlers
+ //
+ Status = InitializeException (&gCpu);
+
+ //
+ // Install CPU Architectural Protocol
+ //
+ NewHandle = NULL;
+ Status = gBS->InstallProtocolInterface (
+ &NewHandle,
+ &gEfiCpuArchProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &gCpu
+ );
+
+ ASSERT_EFI_ERROR (Status);
+
+ Status = REPORT_STATUS_CODE_EX (
+ EFI_PROGRESS_CODE,
+ EFI_COMPUTING_UNIT_HOST_PROCESSOR | EFI_CU_HP_PC_DXE_STEP1,
+ 0,
+ &gEfiCallerIdGuid,
+ NULL,
+ NULL,
+ 0
+ );
+
+ //
+ // Refresh memory space attributes according to MTRRs
+ //
+ Status = RefreshGcdMemoryAttributes ();
+ mIsFlushingGCD = FALSE;
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ Status = REPORT_STATUS_CODE_EX (
+ EFI_PROGRESS_CODE,
+ EFI_COMPUTING_UNIT_HOST_PROCESSOR | EFI_CU_HP_PC_DXE_STEP2,
+ 0,
+ &gEfiCallerIdGuid,
+ NULL,
+ NULL,
+ 0
+ );
+
+ Status = gBS->LocateProtocol (&gEfiMetronomeArchProtocolGuid, NULL, (VOID **) &mMetronome);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = REPORT_STATUS_CODE_EX (
+ EFI_PROGRESS_CODE,
+ EFI_COMPUTING_UNIT_HOST_PROCESSOR | EFI_CU_HP_PC_DXE_STEP3,
+ 0,
+ &gEfiCallerIdGuid,
+ NULL,
+ NULL,
+ 0
+ );
+
+ Status = REPORT_STATUS_CODE_EX (
+ EFI_PROGRESS_CODE,
+ EFI_COMPUTING_UNIT_HOST_PROCESSOR | EFI_CU_HP_PC_DXE_STEP4,
+ 0,
+ &gEfiCallerIdGuid,
+ NULL,
+ NULL,
+ 0
+ );
+
+ //
+ // Initialize MP Support if necessary
+ //
+ Status = InitializeMpSupport (ImageHandle, SystemTable);
+
+ Status = REPORT_STATUS_CODE_EX (
+ EFI_PROGRESS_CODE,
+ EFI_COMPUTING_UNIT_HOST_PROCESSOR | EFI_CU_HP_PC_DXE_END,
+ 0,
+ &gEfiCallerIdGuid,
+ NULL,
+ NULL,
+ 0
+ );
+ //
+ // Create an EndOfDxe protocol callback event
+ //
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ (EFI_EVENT_NOTIFY) CpuInitBeforeBoot,
+ NULL,
+ &gEfiEndOfDxeEventGroupGuid,
+ &EndOfDxeEvent
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = EfiCreateEventLegacyBootEx (
+ TPL_CALLBACK,
+ (EFI_EVENT_NOTIFY) CpuInitBeforeBoot,
+ NULL,
+ &LegacyBootEvent
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Determine the processor core frequency
+
+ @retval Processor core frequency multiplied by 3
+
+**/
+UINT16
+DetermineiFsbFromMsr (
+ VOID
+ )
+{
+ UINT64 FrequencyIndex;
+
+ //
+ // Determine the processor core frequency
+ //
+ FrequencyIndex = (AsmReadMsr64 (BSEL_CR_OVERCLOCK_CONTROL)) & FUSE_BSEL_MASK;
+ if (AsmReadMsr64 (BSEL_CR_OVERCLOCK_CONTROL) & BIT5) {
+ //
+ //maybe change to (FrequencyIndex&0x3)+12 if Lookup table size increases on B-Step
+ //
+ return miFSBFrequencyTable[12];
+ } else if (AsmReadMsr64 (BSEL_CR_OVERCLOCK_CONTROL) & BIT28) {
+ //
+ // Bit 28 combined with bits[0:1] gives us unique lookup value.
+ // When BIT28 is set, Table offset will be 8 + bits[1:0] of MSR
+ //
+ return miFSBFrequencyTable[(FrequencyIndex&0x3)+8];
+ } else {
+ return miFSBFrequencyTable[FrequencyIndex];
+ }
+}
+
+/**
+ Returns the actual CPU core frequency in MHz.
+
+ @param[in] Metronome Metronome protocol
+ @param[out] Frequency Pointer to the CPU core frequency
+
+ @retval EFI_SUCCESS If the frequency is returned successfully
+ @retval EFI_INVALID_PARAMETER If the input parameter is wrong
+
+**/
+EFI_STATUS
+GetActualFrequency (
+ IN EFI_METRONOME_ARCH_PROTOCOL *Metronome,
+ OUT UINT64 *Frequency
+ )
+{
+ UINT64 BeginValue;
+ UINT64 EndValue;
+ UINTN TickCount;
+ BOOLEAN mInterruptState;
+ EFI_STATUS Status;
+ UINT64 TotalValue;
+
+ if (Metronome == NULL || Frequency == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if (mCpuFrequency == 0) {
+ *Frequency = 0;
+
+ //
+ // In order to calculate the actual CPU frequency, we keep track of the CPU Tsc value (which
+ // increases by 1 for every cycle) for a know period of time. The Metronome is not accurate
+ // for the 1st tick, so I choose to wait for 100 ticks, thus the error can be control to be
+ // lower than 1%.
+ //
+ CpuGetInterruptState (&gCpu, &mInterruptState);
+ if (mInterruptState) {
+ DisableInterrupt (&gCpu);
+ }
+ //
+ // Wait for 3000us = 3ms for the calculation
+ // It needs a precise timer to calculate the ticks
+ //
+ TickCount = SAMPLE_TICK_COUNT *4;
+ while (TRUE) {
+ BeginValue = AsmReadTsc ();
+ Status = Metronome->WaitForTick (Metronome, (UINT32)TickCount);
+ EndValue = AsmReadTsc ();
+ if (!EFI_ERROR (Status)) {
+ TotalValue = EndValue - BeginValue;
+ break;
+ }
+ }
+ if (mInterruptState) {
+ EnableInterrupt (&gCpu);
+ }
+
+ mCpuFrequency = MultU64x32 (TotalValue, 10);
+ mCpuFrequency = DivU64x32 (mCpuFrequency, Metronome->TickPeriod * (UINT32)TickCount);
+
+ }
+ *Frequency = mCpuFrequency;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Create Perform Final Init before boot to OS
+
+ @param[in] Event A pointer to the Event that triggered the callback.
+ @param[in] Context A pointer to private data registered with the callback function.
+
+**/
+VOID
+CpuInitBeforeBoot (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+ VOID *ProtocolPointer;
+ EFI_MP_SERVICES_PROTOCOL *MpService;
+
+ Status = gBS->LocateProtocol (&gEfiDxeSmmReadyToLockProtocolGuid, NULL, (VOID **) &ProtocolPointer);
+ if (EFI_SUCCESS != Status) {
+ return ;
+ }
+
+ Status = gBS->LocateProtocol (
+ &gEfiMpServiceProtocolGuid,
+ NULL,
+ (VOID **) &MpService
+ );
+ if (!EFI_ERROR (Status)) {
+ //
+ // Configure for BSP first
+ //
+ ApCpuInitBeforeBoot();
+ //
+ // Confiture the rest APs
+ //
+ Status = MpService->StartupAllAPs (
+ MpService,
+ (EFI_AP_PROCEDURE) ApCpuInitBeforeBoot,
+ TRUE,
+ NULL,
+ 0,
+ NULL,
+ NULL
+ );
+ }
+
+ return ;
+}
+
+/**
+ Perform final Inititialization before boot to OS
+
+ @param[in] None
+
+ @retval None
+**/
+VOID
+ApCpuInitBeforeBoot (
+ VOID
+ )
+{
+}
diff --git a/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/CpuDataStruct.h b/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/CpuDataStruct.h
new file mode 100644
index 0000000000..5d61762969
--- /dev/null
+++ b/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/CpuDataStruct.h
@@ -0,0 +1,121 @@
+/** @file
+
+ Copyright (c) 1999 - 2015, 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_DATA_STRUCT_H
+#define _CPU_DATA_STRUCT_H
+
+#include <Guid/AcpiVariableCompatibility.h>
+//
+// The data saved in SMRAM.
+// In S3 path, CPUS3 runs before SMMS3. SMRAM is open at that time.
+//
+
+#define EFI_SMRAM_CPU_NVS_HEADER_GUID \
+ { \
+ 0x429501d9, 0xe447, 0x40f4, 0x86, 0x7b, 0x75, 0xc9, 0x3a, 0x1d, 0xb5, 0x4e \
+ }
+
+typedef struct {
+ //
+ // Guid as Signature.
+ //
+ EFI_GUID HeaderGuid;
+ EFI_PHYSICAL_ADDRESS AcpiCpuPointer;
+ ACPI_CPU_DATA_COMPATIBILITY AcpiCpuData;
+
+ //
+ // It points the data defined below.
+ //
+ EFI_PHYSICAL_ADDRESS GdtrProfileOffset;
+ EFI_PHYSICAL_ADDRESS GdtOffset;
+ EFI_PHYSICAL_ADDRESS IdtrProfileOffset;
+ EFI_PHYSICAL_ADDRESS IdtOffset;
+ EFI_PHYSICAL_ADDRESS CpuPrivateDataOffset;
+ EFI_PHYSICAL_ADDRESS S3BootScriptTableOffset;
+ EFI_PHYSICAL_ADDRESS S3BspMtrrTableOffset;
+ EFI_PHYSICAL_ADDRESS MicrocodePointerBufferOffset; // It is pointer to pointer array.
+ EFI_PHYSICAL_ADDRESS MicrocodeDataBufferOffset; // It is pointer to the data.
+
+ //
+ // We need put all the data buffer here as well.
+ // These data will be copied to original location in S3.
+ //
+
+ //
+ // DataBuffer size
+ //
+ UINT32 GdtrProfileSize;
+ UINT32 GdtSize;
+ UINT32 IdtrProfileSize;
+ UINT32 IdtSize;
+ UINT32 CpuPrivateDataSize;
+ UINT32 S3BootScriptTableSize;
+ UINT32 S3BspMtrrTableSize;
+ UINT32 MicrocodePointerBufferSize;
+ UINT32 MicrocodeDataBufferSize;
+} SMRAM_CPU_DATA;
+
+typedef struct {
+ UINT32 RegEax;
+ UINT32 RegEbx;
+ UINT32 RegEcx;
+ UINT32 RegEdx;
+} EFI_CPUID_REGISTER;
+
+typedef struct {
+ UINT32 HeaderVersion;
+ UINT32 UpdateRevision;
+ UINT32 Date;
+ UINT32 ProcessorId;
+ UINT32 Checksum;
+ UINT32 LoaderRevision;
+ UINT32 ProcessorFlags;
+ UINT32 DataSize;
+ UINT32 TotalSize;
+ UINT8 Reserved[12];
+} EFI_CPU_MICROCODE_HEADER;
+
+typedef struct {
+ UINT32 ExtSigCount;
+ UINT32 ExtChecksum;
+ UINT8 Reserved[12];
+ UINT32 ProcessorId;
+ UINT32 ProcessorFlags;
+ UINT32 Checksum;
+} EFI_CPU_MICROCODE_EXT_HEADER;
+
+typedef struct {
+ UINT32 ExtendedSignatureCount;
+ UINT32 ExtendedTableChecksum;
+ UINT8 Reserved[12];
+} EFI_CPU_MICROCODE_EXTENDED_TABLE_HEADER;
+
+typedef struct {
+ UINT32 ProcessorSignature;
+ UINT32 ProcessorFlag;
+ UINT32 ProcessorChecksum;
+} EFI_CPU_MICROCODE_EXTENDED_TABLE;
+
+typedef struct {
+ UINT32 Stepping : 4;
+ UINT32 Model : 4;
+ UINT32 Family : 4;
+ UINT32 Type : 2;
+ UINT32 Reserved1 : 2;
+ UINT32 ExtendedModel : 4;
+ UINT32 ExtendedFamily : 8;
+ UINT32 Reserved2 : 4;
+} EFI_CPU_VERSION;
+
+#endif
diff --git a/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/CpuDxe.h b/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/CpuDxe.h
new file mode 100644
index 0000000000..9ead237ffe
--- /dev/null
+++ b/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/CpuDxe.h
@@ -0,0 +1,240 @@
+/** @file
+ Private data structures.
+
+ Copyright (c) 1999 - 2015, 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_DXE_H
+#define _CPU_DXE_H
+
+#include <PiDxe.h>
+
+#include <Guid/StatusCodeDataTypeId.h>
+#include <Guid/AcpiVariableCompatibility.h>
+#include <Guid/GlobalVariable.h>
+#include <Guid/EventGroup.h>
+
+#include <Protocol/Cpu.h>
+#include <Protocol/MpService.h>
+#include <Protocol/Metronome.h>
+#include <Protocol/SmmBase2.h>
+#include <Protocol/SmmAccess2.h>
+#include <Protocol/SmmControl2.h>
+#include <Protocol/ExitPmAuth.h>
+#include <Protocol/DxeSmmReadyToLock.h>
+
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/ReportStatusCodeLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/BaseLib.h>
+#include <Library/UefiLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/HobLib.h>
+#include <Library/DxeServicesTableLib.h>
+
+#include <IndustryStandard/SmBios.h>
+
+#include "CpuRegs.h"
+#include "CpuDataStruct.h"
+
+#define BSEL_CR_OVERCLOCK_CONTROL 0xCD
+#define FUSE_BSEL_MASK 0x07
+
+#define INTERRUPT_VECTOR_NUMBER 256
+#define INTERRUPT_GATE_ATTRIBUTE 0x8e00
+#define NUMBER_OF_MICROCODE_UPDATE 10
+
+extern EFI_GUID gEfiHtBistHobGuid;
+
+#define TRIGGER_MODE_EDGE 0x0
+#define TRIGGER_MODE_LEVEL 0x1
+#define SINGLE_THREAD_BOOT_FLAG 0
+
+#define EfiProcessorFamilyIntelAtom 0x2B
+
+#define SMM_FROM_SMBASE_DRIVER 0x55
+
+#define SMM_FROM_SMBASE_DRIVER_BOOTTIME 0x0
+#define SMM_FROM_SMBASE_DRIVER_RUNTIME 0x1
+#define SMM_FROM_SMBASE_DRIVER_LOCK 0x2
+//
+// This value should be same as the one in CPU driver.
+//
+#define SMM_FROM_CPU_DRIVER_SAVE_INFO 0x81
+
+#define EFI_CU_HP_PC_DXE_INIT (EFI_SUBCLASS_SPECIFIC | 0x00000020)
+#define EFI_CU_HP_PC_DXE_STEP1 (EFI_SUBCLASS_SPECIFIC | 0x00000021)
+#define EFI_CU_HP_PC_DXE_STEP2 (EFI_SUBCLASS_SPECIFIC | 0x00000022)
+#define EFI_CU_HP_PC_DXE_STEP3 (EFI_SUBCLASS_SPECIFIC | 0x00000023)
+#define EFI_CU_HP_PC_DXE_STEP4 (EFI_SUBCLASS_SPECIFIC | 0x00000024)
+#define EFI_CU_HP_PC_DXE_END (EFI_SUBCLASS_SPECIFIC | 0x0000002F)
+#define EfiMakeCpuVersion(f, m, s) \
+ (((UINT32) (f) << 16) | ((UINT32) (m) << 8) | ((UINT32) (s)))
+
+extern
+VOID
+InitializeSelectors (
+ VOID
+ );
+
+//
+// This is the string tool generated data representing our strings.
+//
+extern UINT8 STRING_ARRAY_NAME[];
+
+typedef struct {
+ VOID *Start;
+ UINTN Size;
+ UINTN FixOffset;
+} INTERRUPT_HANDLER_TEMPLATE_MAP;
+
+//
+// Function declarations
+//
+EFI_STATUS
+InitializeMicrocode (
+ IN EFI_CPU_MICROCODE_HEADER **MicrocodePointerBuffer,
+ OUT UINT32 *FailedRevision,
+ IN BOOLEAN IsBsp
+ );
+
+EFI_STATUS
+InitializeMpSupport (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+VOID
+ReadMtrrRegisters (
+ VOID
+ );
+
+VOID
+EFIAPI
+MpMtrrSynchUp (
+ IN VOID *Buffer
+ );
+
+EFI_STATUS
+LoadAllMicrocodeUpdates (
+ VOID
+ );
+
+VOID
+FreeAllMicrocodeUpdates (
+ VOID
+ );
+
+EFI_STATUS
+CheckIncompatibleFsb (
+ IN UINTN CpuNumber,
+ IN UINT64 ActualFsb,
+ IN UINT64 IntendFsb
+ );
+
+EFI_STATUS
+CheckBspBusSpeed (
+ IN EFI_METRONOME_ARCH_PROTOCOL *Metronome
+ );
+
+EFI_STATUS
+GetActualFrequency (
+ IN EFI_METRONOME_ARCH_PROTOCOL *Metronome,
+ OUT UINT64 *Frequency
+ );
+UINT16
+DetermineiFsbFromMsr (
+ VOID
+ );
+
+EFI_STATUS
+Actual2StandardFrequency (
+ IN UINT64 Actual,
+ IN UINT32 Ratio,
+ OUT UINT64 *Standard
+ );
+
+EFI_STATUS
+EnableCpuIdMaximumValueLimit (
+ BOOLEAN LimitCpuidMaximumValue
+ );
+
+EFI_STATUS
+CheckMicrocodeUpdate (
+ IN UINTN CpuNumber,
+ IN EFI_STATUS Status,
+ IN UINT32 FailedRevision
+ );
+
+VOID
+GetTemplateAddressMap (
+ OUT INTERRUPT_HANDLER_TEMPLATE_MAP *AddressMap
+ );
+
+VOID
+CpuEnableInterrupt (
+ VOID
+ );
+
+VOID
+CpuDisableInterrupt (
+ VOID
+ );
+
+UINT16
+GetCodeSegment (
+ VOID
+ );
+
+VOID
+CpuInitFloatPointUnit (
+ VOID
+ );
+
+//
+// Structures
+//
+typedef struct {
+ EFI_HANDLE Handle;
+
+ EFI_CPU_ARCH_PROTOCOL Cpu;
+
+ //
+ // Local Data for CPU interface goes here
+ //
+} CPU_ARCH_PROTOCOL_PRIVATE;
+
+VOID
+CpuInitBeforeBoot (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+VOID
+ApCpuInitBeforeBoot ();
+
+VOID
+PCIConfigWA (
+ EFI_EVENT Event,
+ VOID *Context
+ );
+
+#define CPU_ARCH_PROTOCOL_PRIVATE_DATA_FROM_THIS(a) \
+ CR (a, \
+ CPU_ARCH_PROTOCOL_PRIVATE, \
+ Cpu, \
+ CPU_ARCH_PROT_PRIVATE_SIGNATURE \
+ )
+
+#endif
diff --git a/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/CpuRegs.h b/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/CpuRegs.h
new file mode 100644
index 0000000000..5dd1d959e0
--- /dev/null
+++ b/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/CpuRegs.h
@@ -0,0 +1,410 @@
+/** @file
+ Definitions of CPU registers
+
+@brief
+
+ Conventions:
+
+ - Prefixes:
+ Definitions beginning with "MSR_" are MSRs
+ Definitions beginning with "R_" are registers
+ Definitions beginning with "B_" are bits within registers
+ Definitions beginning with "V_" are meaningful values of bits within the registers
+ Definitions beginning with "S_" are register sizes
+ Definitions beginning with "N_" are the bit position
+
+ Copyright (c) 2004 - 2015, 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_REGS_H_
+#define _CPU_REGS_H_
+
+//
+// Local APIC defines
+//
+#define APIC_REGISTER_LOCAL_ID_OFFSET 0x00000020
+#define APIC_REGISTER_APIC_VERSION_OFFSET 0x00000030
+#define APIC_REGISTER_SPURIOUS_VECTOR_OFFSET 0x000000F0
+#define APIC_REGISTER_ICR_LOW_OFFSET 0x00000300
+#define APIC_REGISTER_ICR_HIGH_OFFSET 0x00000310
+#define APIC_REGISTER_LINT0_VECTOR_OFFSET 0x00000350
+#define APIC_REGISTER_LINT1_VECTOR_OFFSET 0x00000360
+
+#define BROADCAST_MODE_SPECIFY_CPU 0x00
+#define BROADCAST_MODE_ALL_INCLUDING_SELF 0x01
+#define BROADCAST_MODE_ALL_EXCLUDING_SELF 0x02
+
+#ifndef DELIVERY_MODE_FIXED
+#define DELIVERY_MODE_FIXED 0x0
+#endif
+#ifndef DELIVERY_MODE_LOWEST_PRIORITY
+#define DELIVERY_MODE_LOWEST_PRIORITY 0x1
+#endif
+#ifndef DELIVERY_MODE_SMI
+#define DELIVERY_MODE_SMI 0x2
+#endif
+#ifndef DELIVERY_MODE_REMOTE_READ
+#define DELIVERY_MODE_REMOTE_READ 0x3
+#endif
+#ifndef DELIVERY_MODE_NMI
+#define DELIVERY_MODE_NMI 0x4
+#endif
+#ifndef DELIVERY_MODE_INIT
+#define DELIVERY_MODE_INIT 0x5
+#endif
+#ifndef DELIVERY_MODE_SIPI
+#define DELIVERY_MODE_SIPI 0x6
+#endif
+#ifndef DELIVERY_MODE_MAX
+#define DELIVERY_MODE_MAX 0x7
+#endif
+
+#define EFI_CACHE_UNCACHEABLE 0
+#define EFI_CACHE_WRITECOMBINING 1
+#define EFI_CACHE_WRITETHROUGH 4
+#define EFI_CACHE_WRITEPROTECTED 5
+#define EFI_CACHE_WRITEBACK 6
+
+//
+// CPUID defines
+//
+#define EFI_CPUID_SIGNATURE 0x0
+
+#define EFI_CPUID_VERSION_INFO 0x1
+#define B_EFI_CPUID_VERSION_INFO_EAX_MASK 0x0FFF0FFF
+#define B_EFI_CPUID_VERSION_INFO_EAX_FULL_FAMILY_MODEL_MASK 0x0FFF0FF0
+#define B_EFI_CPUID_VERSION_INFO_EAX_EXT_FAMILY_ID_MASK 0x0FF00000
+#define B_EFI_CPUID_VERSION_INFO_EAX_EXT_MODEL_ID_MASK 0x000F0000
+#define N_EFI_CPUID_VERSION_INFO_EAX_EXT_FAMILY_ID 20
+#define N_EFI_CPUID_VERSION_INFO_EAX_EXT_MODEL_ID 16
+#define N_EFI_CPUID_VERSION_INFO_EAX_TYPE 12
+#define N_EFI_CPUID_VERSION_INFO_EAX_FAMILY_ID 8
+#define N_EFI_CPUID_VERSION_INFO_EAX_MODEL 4
+#define N_EFI_CPUID_VERSION_INFO_EAX_STEPPING_ID 0
+#define B_EFI_CPUID_VERSION_INFO_EBX_DEFAULT_APIC_ID (BIT31 | BIT30 | BIT29 | BIT28 | BIT27 | BIT26 | BIT25 | BIT24)
+#define B_EFI_CPUID_VERSION_INFO_EBX_LOGICAL_CPU_PER_PACKAGE (BIT23 | BIT22 | BIT21 | BIT20 | BIT19 | BIT18 | BIT17 | BIT16)
+#define B_EFI_CPUID_VERSION_INFO_EBX_CLFLUSH_CHUNK_COUNT (BIT15 | BIT14 | BIT13 | BIT12 | BIT11 | BIT10 | BIT9 | BIT8)
+#define B_EFI_CPUID_VERSION_INFO_ECX_AES BIT25
+#define B_EFI_CPUID_VERSION_INFO_ECX_XAPIC BIT21
+#define B_EFI_CPUID_VERSION_INFO_ECX_SSE4_2 BIT20
+#define B_EFI_CPUID_VERSION_INFO_ECX_SSE4_1 BIT19
+#define B_EFI_CPUID_VERSION_INFO_ECX_DCA BIT18
+#define B_EFI_CPUID_VERSION_INFO_ECX_XTPR_UPDATE BIT14
+#define B_EFI_CPUID_VERSION_INFO_ECX_CMPXCHG16B BIT13
+#define B_EFI_CPUID_VERSION_INFO_ECX_L1_CONTEXT_ID BIT10
+#define B_EFI_CPUID_VERSION_INFO_ECX_SUP_SSE3 BIT9
+#define B_EFI_CPUID_VERSION_INFO_ECX_TM2 BIT8
+#define B_EFI_CPUID_VERSION_INFO_ECX_EIST BIT7
+#define B_EFI_CPUID_VERSION_INFO_ECX_SME BIT6
+#define B_EFI_CPUID_VERSION_INFO_ECX_VME BIT5
+#define B_EFI_CPUID_VERSION_INFO_ECX_QPL BIT4
+#define B_EFI_CPUID_VERSION_INFO_ECX_MWAIT BIT3
+#define B_EFI_CPUID_VERSION_INFO_ECX_SSE3 BIT0
+#define B_EFI_CPUID_VERSION_INFO_EDX_PBE BIT31
+#define B_EFI_CPUID_VERSION_INFO_EDX_THERMAL_CLOCK_CONTROL BIT29
+#define B_EFI_CPUID_VERSION_INFO_EDX_HT BIT28
+#define B_EFI_CPUID_VERSION_INFO_EDX_SELF_SNOOP BIT27
+#define B_EFI_CPUID_VERSION_INFO_EDX_SSE2 BIT26
+#define B_EFI_CPUID_VERSION_INFO_EDX_SSE BIT25
+#define B_EFI_CPUID_VERSION_INFO_EDX_FAST_SAVE_RESTORE BIT24
+#define B_EFI_CPUID_VERSION_INFO_EDX_MMX BIT23
+#define B_EFI_CPUID_VERSION_INFO_EDX_ACPI_SUPPORT BIT22
+#define B_EFI_CPUID_VERSION_INFO_EDX_DEBUG_TRACE_STORE BIT21
+#define B_EFI_CPUID_VERSION_INFO_EDX_CLFLUSH_INTR BIT19
+#define B_EFI_CPUID_VERSION_INFO_EDX_CPU_SERIAL_NUMBER BIT18
+#define B_EFI_CPUID_VERSION_INFO_EDX_PSE BIT17
+#define B_EFI_CPUID_VERSION_INFO_EDX_PAT BIT16
+#define B_EFI_CPUID_VERSION_INFO_EDX_CON_MOVE_INTR BIT15
+#define B_EFI_CPUID_VERSION_INFO_EDX_MCA BIT14
+#define B_EFI_CPUID_VERSION_INFO_EDX_PGE BIT13
+#define B_EFI_CPUID_VERSION_INFO_EDX_MTRR BIT12
+#define B_EFI_CPUID_VERSION_INFO_EDX_SEP BIT11
+#define B_EFI_CPUID_VERSION_INFO_EDX_ON_CHIP_APIC BIT9
+#define B_EFI_CPUID_VERSION_INFO_EDX_CMPXCHG8 BIT8
+#define B_EFI_CPUID_VERSION_INFO_EDX_MCE BIT7
+#define B_EFI_CPUID_VERSION_INFO_EDX_PAE BIT6
+#define B_EFI_CPUID_VERSION_INFO_EDX_MSR BIT5
+#define B_EFI_CPUID_VERSION_INFO_EDX_TIME_STAMP_COUNTER BIT4
+#define B_EFI_CPUID_VERSION_INFO_EDX_PAGE_SIZE_EXT BIT3
+#define B_EFI_CPUID_VERSION_INFO_EDX_DEBUG_EXT BIT2
+#define B_EFI_CPUID_VERSION_INFO_EDX_VME_8086 BIT1
+#define B_EFI_CPUID_VERSION_INFO_EDX_FP_386 BIT0
+
+#define EFI_CPUID_CACHE_INFO 0x2
+#define EFI_CPUID_SERIAL_NUMBER 0x3
+
+#define EFI_CPUID_CACHE_PARAMS 0x4
+#define B_EFI_CPUID_CACHE_PARAMS_EAX_MAX_CORES_IN_PACKAGE (BIT31 | BIT30 | BIT29 | BIT28 | BIT27 | BIT26)
+#define B_EFI_CPUID_CACHE_PARAMS_EAX_TOTAL_THREADS_SHARE_CACHE (BIT25 | BIT24 | BIT23 | BIT22 | BIT21 | BIT20 | BIT19 | BIT18 | BIT17 | BIT16 | BIT15 | BIT14)
+#define B_EFI_CPUID_CACHE_PARAMS_EAX_FULLY_ASSOCIATIVE_CACHE BIT9
+#define B_EFI_CPUID_CACHE_PARAMS_EAX_SELF_INITIALIZING BIT8
+#define B_EFI_CPUID_CACHE_PARAMS_EAX_CACHE_LEVEL (BIT7 | BIT6 | BIT5)
+#define B_EFI_CPUID_CACHE_PARAMS_EAX_CACHE_TYPE (BIT4 | BIT3 | BIT2 | BIT1 | BIT0)
+#define B_EFI_CPUID_CACHE_PARAMS_EBX_WAYS_OF_ASSOCIATIVITY (BIT31 | BIT30 | BIT29 | BIT28 | BIT27 | BIT26 | BIT25 | BIT24 | BIT23 | BIT22)
+#define B_EFI_CPUID_CACHE_PARAMS_EBX_PHYSICAL_LINE_PARTITIONS (BIT21 | BIT20 | BIT19 | BIT18 | BIT17 | BIT16 | BIT15 | BIT14 | BIT13 | BIT12)
+#define B_EFI_CPUID_CACHE_PARAMS_EBX_SYSTEM_COHERENCY_LINE_SIZE (BIT11 | BIT10 | BIT9 | BIT8 | BIT7 | BIT6 | BIT5 | BIT4 | BIT3 | BIT2 | BIT1 | BIT0)
+#define B_EFI_CPUID_CACHE_PARAMS_EDX_CACHE_INCLUSIVE_IN_LOWER_CACHE BIT1
+#define B_EFI_CPUID_CACHE_PARAMS_EDX_WBINVD_INVD_ON_LOWER_CACHE BIT0
+#define V_CPUID_CACHE_TYPE_MASK 0x1F
+#define B_CPUID_CACHE_TYPE_DATA 0x1
+#define B_CPUID_CACHE_TYPE_INSTRUCTION 0x2
+#define B_CPUID_CACHE_TYPE_UNIFIED 0x3
+#define V_CPUID_CACHE_LEVEL_MASK 0xE0
+#define B_CPUID_CACHE_LEVEL_SHIFT 5
+#define B_CPUID_CACHE_PARAMS_WAYS_SHIFT 22
+#define B_CPUID_CACHE_PARAMS_PARTITIONS_SHIFT 12
+
+#define EFI_CPUID_MONITOR_MWAIT_PARAMS 0x5
+#define B_EFI_CPUID_MONITOR_MWAIT_ECX_INTERRUPTS_BREAK_MWAIT BIT1
+#define B_EFI_CPUID_MONITOR_MWAIT_ECX_MWAIT_SUPPORT BIT0
+#define B_EFI_CPUID_MONITOR_MWAIT_EDX_PARAMS_C7 (BIT31 | BIT30 | BIT29 | BIT28)
+#define N_EFI_CPUID_MONITOR_MWAIT_EDX_PARAMS_C7 28
+#define B_EFI_CPUID_MONITOR_MWAIT_EDX_PARAMS_C6 (BIT27 | BIT26 | BIT25 | BIT24)
+#define N_EFI_CPUID_MONITOR_MWAIT_EDX_PARAMS_C6 24
+#define B_EFI_CPUID_MONITOR_MWAIT_EDX_PARAMS_C5 (BIT23 | BIT22 | BIT21 | BIT20)
+#define N_EFI_CPUID_MONITOR_MWAIT_EDX_PARAMS_C5 20
+#define B_EFI_CPUID_MONITOR_MWAIT_EDX_PARAMS_C4 (BIT19 | BIT18 | BIT17 | BIT16)
+#define N_EFI_CPUID_MONITOR_MWAIT_EDX_PARAMS_C4 16
+#define B_EFI_CPUID_MONITOR_MWAIT_EDX_PARAMS_C3 (BIT15 | BIT14 | BIT13 | BIT12)
+#define N_EFI_CPUID_MONITOR_MWAIT_EDX_PARAMS_C3 12
+#define B_EFI_CPUID_MONITOR_MWAIT_EDX_PARAMS_C2 (BIT11 | BIT10 | BIT9 | BIT8)
+#define N_EFI_CPUID_MONITOR_MWAIT_EDX_PARAMS_C2 8
+#define B_EFI_CPUID_MONITOR_MWAIT_EDX_PARAMS_C1 (BIT7 | BIT6 | BIT5 | BIT4)
+#define N_EFI_CPUID_MONITOR_MWAIT_EDX_PARAMS_C1 4
+#define B_EFI_CPUID_MONITOR_MWAIT_EDX_PARAMS_C0 (BIT3 | BIT2 | BIT1 | BIT0)
+#define N_EFI_CPUID_MONITOR_MWAIT_EDX_PARAMS_C0 0
+
+#define EFI_CPUID_POWER_MANAGEMENT_PARAMS 0x6
+#define EFI_CPUID_POWER_MANAGEMENT_EAX_DTS BIT0
+#define EFI_CPUID_POWER_MANAGEMENT_EBX_NUM_INT_THRESHOLDS (BIT3 | BIT2 | BIT1 | BIT0)
+#define EFI_CPUID_POWER_MANAGEMENT_ECX_HW_COORDINATION_FEEDBACK BIT0
+
+#define EFI_CPUID_REV7 0x7
+#define EFI_CPUID_REV8 0x8
+#define EFI_CPUID_DCA_PARAMS 0x9
+#define EFI_CPUID_ARCH_PERF_MON 0xA
+#define EFI_CPUID_CORE_TOPOLOGY 0xB
+
+#define EFI_CPUID_EXTENDED_FUNCTION 0x80000000
+
+#define EFI_CPUID_EXTENDED_FEATURE_BITS 0x80000001
+#define EFI_CPUID_EXTENDED_FEATURE_BITS_ECX_LAHF_SAHF BIT0
+#define EFI_CPUID_EXTENDED_FEATURE_BITS_EDX_XD BIT20
+#define EFI_CPUID_EXTENDED_FEATURE_BITS_EDX_SYSCALL BIT11
+
+//
+// This constant defines the maximum length of the CPU brand string. According to the
+// IA manual, the brand string is in EAX through EDX (thus 16 bytes) after executing
+// the CPUID instructions with EAX as 80000002, 80000003, 80000004.
+//
+#define MAXIMUM_CPU_BRAND_STRING_LENGTH 48
+
+#define EFI_CPUID_BRAND_STRING1 0x80000002
+#define EFI_CPUID_BRAND_STRING2 0x80000003
+#define EFI_CPUID_BRAND_STRING3 0x80000004
+
+#define EFI_CPUID_ADVANCED_POWER_MANAGEMENT 0x80000007
+#define EFI_CPUID_ADVANCED_POWER_MANAGEMENT_EDX_TSC_INVARIANCE BIT8
+
+#define EFI_CPUID_VIRT_PHYS_ADDRESS_SIZE 0x80000008
+#define B_EFI_CPUID_VIRTUAL_ADDRESS_BITS (BIT15 | BIT14 | BIT13 | BIT12 | BIT11 | BIT10 | BIT9 | BIT8)
+#define B_EFI_CPUID_PHYSICAL_ADDRESS_BITS (BIT7 | BIT6 | BIT5 | BIT4 | BIT3 | BIT2 | BIT1 | BIT0)
+
+//
+// Common MSR
+//
+#define EFI_MSR_IA32_PLATFORM_ID 0x00000017
+#define N_EFI_MSR_IA32_PLATFORM_ID_PLATFORM_ID_BITS 50
+#define B_EFI_MSR_IA32_PLATFORM_ID_PLATFORM_ID_BITS_MASK (BIT52 | BIT51 | BIT50)
+#define N_EFI_MSR_IA32_PLATFORM_ID_PLATFORM_ID_BITS_MASK_START 50
+#define N_EFI_MSR_IA32_PLATFORM_ID_PLATFORM_ID_BITS_MASK_END 52
+
+#ifndef EFI_MSR_IA32_APIC_BASE
+#define EFI_MSR_IA32_APIC_BASE 0x0000001B
+
+#define B_EFI_MSR_IA32_APIC_BASE_APIC_BASE_ADDRESS 0xFFFFFF000 //For Nehalem, base address can be up to 43 bits but not cover here yet
+#define B_EFI_MSR_IA32_APIC_BASE_APIC_GLOBAL_ENABLE BIT11
+#define B_EFI_MSR_IA32_APIC_BASE_M_XAPIC BIT10
+#define B_EFI_MSR_IA32_APIC_BASE_BSP BIT8
+#endif // EFI_MSR_IA32_APIC_BASE
+//
+// Local APIC defines, offset from APIC base address
+//
+#define APIC_REGISTER_LOCAL_ID_OFFSET 0x00000020
+#define N_APIC_REGISTER_LOCAL_ID_OFFSET_XAPIC_ID_MASK 24
+#define B_APIC_REGISTER_LOCAL_ID_OFFSET_XAPIC_ID_MASK 0xFF000000
+
+#define APIC_REGISTER_APIC_VERSION_OFFSET 0x00000030
+#define B_APIC_REGISTER_APIC_VERSION_OFFSET_VERSION_MASK 0xFF
+
+#define APIC_REGISTER_SPURIOUS_VECTOR_OFFSET 0x000000F0
+#define APIC_REGISTER_ICR_LOW_OFFSET 0x00000300
+#define APIC_REGISTER_ICR_HIGH_OFFSET 0x00000310
+#define APIC_REGISTER_LINT0_VECTOR_OFFSET 0x00000350
+#define APIC_REGISTER_LINT1_VECTOR_OFFSET 0x00000360
+
+#define EFI_MSR_IA32_FEATURE_CONTROL 0x0000003A
+#define B_EFI_MSR_IA32_FEATURE_CONTROL_SGE BIT15
+#define B_EFI_MSR_IA32_FEATURE_CONTROL_SLFE (BIT14 | BIT13 | BIT12 | BIT11 | BIT10 | BIT9 | BIT8)
+#define B_EFI_MSR_IA32_FEATURE_CONTROL_SMRR BIT3
+#define B_EFI_MSR_IA32_FEATURE_CONTROL_EVT BIT2
+#define B_EFI_MSR_IA32_FEATURE_CONTROL_ELT BIT1
+#define B_EFI_MSR_IA32_FEATURE_CONTROL_LOCK BIT0
+#define B_EFI_MSR_IA32_FEATURE_CONTROL_VT_SECURE 0x0000FF02
+
+#ifndef EFI_MSR_IA32_BIOS_UPDT_TRIG
+#define EFI_MSR_IA32_BIOS_UPDT_TRIG 0x00000079
+#endif
+#ifndef EFI_MSR_IA32_BIOS_SIGN_ID
+#define EFI_MSR_IA32_BIOS_SIGN_ID 0x0000008B
+#endif
+
+#define EFI_MSR_PMG_CST_CONFIG 0x000000E2
+#define B_EFI_MSR_PMG_CST_CONFIG_CST_CONTROL_LOCK BIT15
+#define B_EFI_MSR_PMG_CST_CONFIG_IO_MWAIT_REDIRECTION_ENABLE BIT10
+#define B_EFI_MSR_PMG_CST_CONFIG_PACKAGE_C_STATE_LIMIT (BIT2 | BIT1 | BIT0)
+
+#define EFI_MSR_PMG_IO_CAPTURE_ADDR 0x000000E4 //For Nehalem Spec: EFI_IA32_PMG_IO_CAPTURE_BASE
+#define N_EFI_MSR_PMG_IO_CAPTURE_ADDR_CST_RANGE 16
+#define B_EFI_MSR_PMG_IO_CAPTURE_ADDR_LVL_2_BASE_ADDRESS_MASK 0xFFFF
+
+#define EFI_MSR_IA32_MPERF 0x000000E7
+#define EFI_MSR_IA32_APERF 0x000000E8
+
+#define EFI_MSR_IA32_MTRR_CAP 0x000000FE
+#define B_EFI_MSR_IA32_MTRR_CAP_EMRR_SUPPORT BIT12
+#define B_EFI_MSR_IA32_MTRR_CAP_SMRR_SUPPORT BIT11
+#define B_EFI_MSR_IA32_MTRR_CAP_WC_SUPPORT BIT10
+#define B_EFI_MSR_IA32_MTRR_CAP_FIXED_SUPPORT BIT8
+#define B_EFI_MSR_IA32_MTRR_CAP_VARIABLE_SUPPORT (BIT7 | BIT6 | BIT5 | BIT4 | BIT3 | BIT2 | BIT1 | BIT0)
+
+#define EFI_MSR_IA32_MCG_CAP 0x00000179
+#define EFI_MSR_IA32_MCG_STATUS 0x0000017A
+
+#define EFI_MSR_IA32_PERF_STS 0x00000198
+#define EFI_MSR_IA32_PERF_CTRL 0x00000199
+
+#ifndef EFI_MSR_IA32_THERM_INTERRUPT
+#define EFI_MSR_IA32_THERM_INTERRUPT 0x0000019B
+#endif
+
+#define B_EFI_MSR_IA32_THERM_INTERRUPT_VIE BIT4
+
+#ifndef EFI_MSR_IA32_THERM_STATUS
+#define EFI_MSR_IA32_THERM_STATUS 0x0000019C
+#endif
+
+#ifndef EFI_MSR_IA32_MISC_ENABLE
+#define EFI_MSR_IA32_MISC_ENABLE 0x000001A0
+#endif
+
+#define B_EFI_MSR_IA32_MISC_ENABLE_XD BIT34
+#define B_EFI_MSR_IA32_MISC_ENABLE_CPUID_MAX BIT22
+#define B_EFI_MSR_IA32_MISC_ENABLE_MONITOR BIT18
+#define B_EFI_MSR_IA32_MISC_ENABLE_TM1_EN BIT3
+
+#define EFI_MSR_SMRR_PHYS_BASE 0x000001F2
+#define EFI_MSR_SMRR_PHYS_MASK 0x000001F3
+
+#define EFI_MSR_CACHE_VARIABLE_MTRR_BASE 0x00000200
+#define EFI_MSR_CACHE_VARIABLE_MTRR_END 0x0000020F
+#define V_EFI_FIXED_MTRR_NUMBER 11
+
+#define EFI_MSR_IA32_MTRR_FIX64K_00000 0x00000250
+#define EFI_MSR_IA32_MTRR_FIX16K_80000 0x00000258
+#define EFI_MSR_IA32_MTRR_FIX16K_A0000 0x00000259
+#define EFI_MSR_IA32_MTRR_FIX4K_C0000 0x00000268
+#define EFI_MSR_IA32_MTRR_FIX4K_C8000 0x00000269
+#define EFI_MSR_IA32_MTRR_FIX4K_D0000 0x0000026A
+#define EFI_MSR_IA32_MTRR_FIX4K_D8000 0x0000026B
+#define EFI_MSR_IA32_MTRR_FIX4K_E0000 0x0000026C
+#define EFI_MSR_IA32_MTRR_FIX4K_E8000 0x0000026D
+#define EFI_MSR_IA32_MTRR_FIX4K_F0000 0x0000026E
+#define EFI_MSR_IA32_MTRR_FIX4K_F8000 0x0000026F
+#define EFI_MSR_CACHE_IA32_MTRR_DEF_TYPE 0x000002FF
+#define B_EFI_MSR_CACHE_MTRR_VALID BIT11
+#define B_EFI_MSR_GLOBAL_MTRR_ENABLE BIT11
+#define B_EFI_MSR_FIXED_MTRR_ENABLE BIT10
+#define B_EFI_MSR_CACHE_MEMORY_TYPE (BIT2 | BIT1 | BIT0)
+
+#define EFI_MSR_VALID_MASK 0xFFFFFFFFF
+#define EFI_CACHE_VALID_ADDRESS 0xFFFFFF000
+#define EFI_SMRR_CACHE_VALID_ADDRESS 0xFFFFF000
+#define EFI_CACHE_VALID_EXTENDED_ADDRESS 0xFFFFFFFFFF000
+
+// Leave one MTRR pairs for OS use
+#define EFI_CACHE_NUM_VAR_MTRR_PAIRS_FOR_OS 1
+#define EFI_CACHE_LAST_VARIABLE_MTRR_FOR_BIOS (EFI_MSR_CACHE_VARIABLE_MTRR_END) - \
+ (EFI_CACHE_NUM_VAR_MTRR_PAIRS_FOR_OS * 2)
+
+#define EFI_MSR_IA32_MC0_CTL 0x00000400
+#define EFI_MSR_IA32_MC0_STATUS 0x00000401
+#define EFI_MSR_IA32_MC0_ADDR 0x00000402
+#define EFI_MSR_IA32_MC0_MISC 0x00000403
+#define EFI_MSR_IA32_MC8_CTL (EFI_IA32_MC0_CTL + (8*4))
+#define EFI_MSR_IA32_MC8_STATUS (EFI_IA32_MC0_STATUS + (8*4))
+
+#define EFI_MSR_APIC_GLOBAL_ENABLE 0x00000800
+#define EFI_MSR_EXT_XAPIC_LOGICAL_APIC_ID 0x00000802
+#define EFI_MSR_EXT_XAPIC_VERSION 0x00000803
+#define B_EFI_MSR_EXT_XAPIC_VERSION_VERSION 0xFF
+#define EFI_MSR_EXT_XAPIC_SVR 0x0000080F
+#define EFI_MSR_EXT_XAPIC_ICR 0x00000830
+#define EFI_MSR_EXT_XAPIC_LVT_LINT0 0x00000835
+#define EFI_MSR_EXT_XAPIC_LVT_LINT1 0x00000836
+
+#define EFI_MSR_IA32_EFER 0xC0000080
+#define B_EFI_MSR_IA32_EFER_NXE BIT11
+#define B_EFI_MSR_IA32_EFER_LMA BIT10
+#define B_EFI_MSR_IA32_EFER_LME BIT8
+#define B_EFI_MSR_IA32_EFER_SCE BIT0
+
+#pragma pack(1)
+
+typedef enum {
+ EnumCpuUarchUnknown = 0,
+ EnumNehalemUarch,
+} EFI_CPU_UARCH;
+
+typedef enum {
+ EnumCpuPlatformUnknown = 0,
+ EnumDesktop,
+ EnumMobile,
+ EnumServer,
+ EnumNetTop
+} EFI_CPU_PLATFORM;
+
+typedef enum {
+ EnumCpuTypeUnknown = 0,
+ EnumAtom,
+ EnumNehalemEx,
+ EnumBloomfield,
+ EnumGainestown,
+ EnumHavendale,
+ EnumLynnfield,
+ EnumAuburndale,
+ EnumClarksfield,
+ EnumPineview,
+ EnumCedarview,
+ EnumValleyview,
+ EnumClarkdale // Havendale 32nm
+} EFI_CPU_TYPE;
+
+typedef enum {
+ EnumCpuFamilyUnknown = 0,
+ EnumFamilyField,
+ EnumFamilyDale
+} EFI_CPU_FAMILY;
+
+#pragma pack()
+
+#endif
diff --git a/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/Exception.h b/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/Exception.h
new file mode 100644
index 0000000000..695670458a
--- /dev/null
+++ b/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/Exception.h
@@ -0,0 +1,71 @@
+/** @file
+ IA32 Exception Includes.
+
+ Copyright (c) 1999 - 2015, 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 _IA32EXCEPTION_H
+#define _IA32EXCEPTION_H
+
+//
+// Driver Consumed Protocol Prototypes
+//
+#include <Protocol/Cpu.h>
+
+#define EFI_STATUS_CODE_DATA_TYPE_EXCEPTION_HANDLER_GUID \
+ { \
+ 0x3BC2BD12, 0xAD2E, 0x11D5, {0x87, 0xDD, 0x00, 0x06, 0x29, 0x45, 0xC3, 0xB9} \
+ }
+
+#define INTERRUPT_HANDLER_DIVIDE_ZERO 0x00
+#define INTERRUPT_HANDLER_DEBUG 0x01
+#define INTERRUPT_HANDLER_NMI 0x02
+#define INTERRUPT_HANDLER_BREAKPOINT 0x03
+#define INTERRUPT_HANDLER_OVERFLOW 0x04
+#define INTERRUPT_HANDLER_BOUND 0x05
+#define INTERRUPT_HANDLER_INVALID_OPCODE 0x06
+#define INTERRUPT_HANDLER_DEVICE_NOT_AVAILABLE 0x07
+#define INTERRUPT_HANDLER_DOUBLE_FAULT 0x08
+#define INTERRUPT_HANDLER_COPROCESSOR_OVERRUN 0x09
+#define INTERRUPT_HANDLER_INVALID_TSS 0x0A
+#define INTERRUPT_HANDLER_SEGMENT_NOT_PRESENT 0x0B
+#define INTERRUPT_HANDLER_STACK_SEGMENT_FAULT 0x0C
+#define INTERRUPT_HANDLER_GP_FAULT 0x0D
+#define INTERRUPT_HANDLER_PAGE_FAULT 0x0E
+#define INTERRUPT_HANDLER_RESERVED 0x0F
+#define INTERRUPT_HANDLER_MATH_FAULT 0x10
+#define INTERRUPT_HANDLER_ALIGNMENT_FAULT 0x11
+#define INTERRUPT_HANDLER_MACHINE_CHECK 0x12
+#define INTERRUPT_HANDLER_STREAMING_SIMD 0x13
+/**
+ @todo add structure description
+
+**/
+typedef struct {
+ EFI_STATUS_CODE_DATA Header;
+ union {
+ EFI_SYSTEM_CONTEXT_IA32 SystemContextIa32;
+ EFI_SYSTEM_CONTEXT_X64 SystemContextX64;
+ } SystemContext;
+} CPU_STATUS_CODE_TEMPLATE;
+
+VOID
+EFIAPI
+CommonExceptionHandler (
+ IN EFI_EXCEPTION_TYPE InterruptType,
+ IN EFI_SYSTEM_CONTEXT SystemContext
+ );
+
+EFI_STATUS
+InitializeException (
+ IN EFI_CPU_ARCH_PROTOCOL *CpuProtocol
+ );
+#endif
diff --git a/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/Ia32/CpuAsm.asm b/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/Ia32/CpuAsm.asm
new file mode 100644
index 0000000000..dfc81eeed8
--- /dev/null
+++ b/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/Ia32/CpuAsm.asm
@@ -0,0 +1,693 @@
+;; @file
+; Assembly code that supports IA32 CPU architectural protocol
+;
+; Copyright (c) 1999 - 2015, 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.
+;;
+ page ,132
+ title CPU ARCHITECTURAL DXE PROTOCOL ASSEMBLY HOOKS
+.686p
+.model flat
+
+.data
+ExternalVectorTablePtr DD ? ; Table of call backs
+CommonInterruptEntry DD CommonEntry ; Address of CommonEntry
+Idtr DW ? ; FWORD for IDT register
+Idtr1 DD ? ; MUST BE IMMEDIATELY AFTER Idtr
+
+EXTRN _mErrorCodeFlag:DWORD ; Error code flags for exceptions
+
+.stack
+.code
+.MMX
+.XMM
+
+include Htequ.inc
+
+UINT8 TYPEDEF BYTE
+UINT16 TYPEDEF WORD
+UINT32 TYPEDEF DWORD
+UINT64 TYPEDEF QWORD
+UINTN TYPEDEF UINT32
+
+;---------------------------------------;
+; _InitializeIdt ;
+;----------------------------------------------------------------------------;
+;
+; Protocol prototype
+; InitializeIdt (
+; IN EFI_CPU_INTERRUPT_HANDLER TableStart,
+; IN UINTN *IdtTablePtr,
+; IN UINT16 IdtLimit
+; )
+;
+; Routine Description:
+;
+; Creates an IDT table starting at IdtTablPtr. It has IdtLimit/8 entries.
+; Table is initialized to intxx where xx is from 00 to number of entries or
+; 100h, whichever is smaller. After table has been initialized the LIDT
+; instruction is invoked.
+;
+; TableStart is the pointer to the callback table and is not used by
+; InitializedIdt but by commonEntry. CommonEntry handles all interrupts,
+; does the context save and calls the callback entry, if non-NULL.
+; It is the responsibility of the callback routine to do hardware EOIs.
+;
+; Arguments:
+;
+; TableStart - Pointer to interrupt callback table
+;
+; IdtTablePtr - Pointer to IDT table
+;
+; IdtLimit - IDT Table limit = number of interrupt entries * 8
+;
+; Returns:
+;
+; Nothing
+;
+;
+; Input: [ebp][0] = Original ebp
+; [ebp][4] = Return address
+; [ebp][8] = TableStart
+; [ebp][0c] = *IdtTablePtr
+; [ebp][10] = IdtLimit
+;
+; Output: Nothing
+;
+; Destroys: Nothing
+;-----------------------------------------------------------------------------;
+
+_InitializeIdt proc near public
+ push ebp ; C prolog
+ mov ebp, esp
+ push edi
+
+ mov eax, [ebp+8] ; Get ExternalVectorTable Address
+ mov ExternalVectorTablePtr, eax
+
+ mov ax, [ebp+10h] ; Get IDT Table limit
+ dec ax
+ mov Idtr, ax
+
+ mov eax, [ebp+0ch] ; Get Start of IDT
+ mov Idtr1, eax
+
+ mov edi, OFFSET Idtr ; Load IDT register
+ lidt FWORD PTR es:[edi]
+
+ pop edi
+ pop ebp
+ ret
+_InitializeIdt endp
+
+;----------------------------------------------------------------------------;
+;
+; Protocol prototype
+; None
+;
+; Routine Description:
+;
+; These routines handle the individual interrupts. These routines always
+; gain control on any interrupt or exception. They save EAX and place
+; the interrupt number in EAX. CommonEntry is then jumped to.
+; instruction is invoked.
+;
+; CommonEntry handles all interrupts,does the context save and calls the
+; callback entry, if non-NULL. It is the responsibility of the callback
+; routine to do hardware EOIs. Callbacks are entered into the table
+; located at TableStart. Entries are modified by the InstallInterruptHandler
+; and UninstallInterruptHandler protocols.
+;
+; Arguments to CommonEntry:
+;
+; EAX - Interrupt or exception number
+;
+; TableStart - Pointer to interrupt callback table
+;
+; Returns:
+;
+; Nothing
+;
+;
+; Output: Nothing
+;
+; Destroys: Nothing
+;-----------------------------------------------------------------------------;
+
+TemplateStart:
+ push eax
+
+ ;mov eax, 0nnh (nn stands for vector number, which will be fixed at runtime
+ DB 0b8h
+VectorNumber:
+ DD 00h
+
+ jmp dword ptr [CommonInterruptEntry];
+TemplateEnd:
+
+CommonEntry:
+
+;---------------------------------------;
+; _CommonEntry ;
+;----------------------------------------------------------------------------;
+; The follow algorithm is used for the common interrupt routine.
+; Entry from each interrupt with a push eax and eax=interrupt number
+
+;
+; +---------------------+
+; + EFlags +
+; +---------------------+
+; + CS +
+; +---------------------+
+; + EIP +
+; +---------------------+
+; + Error Code +
+; +---------------------+
+; + EAX / Vector Number +
+; +---------------------+
+; + EBP +
+; +---------------------+ <-- EBP
+;
+
+ cli
+ ;
+ ; All interrupt handlers are invoked through interrupt gates, so
+ ; IF flag automatically cleared at the entry point
+ ;
+ cmp eax, 32 ; Intel reserved vector for exceptions?
+ jae NoErrorCode
+ bt cs:_mErrorCodeFlag, eax
+ jc @F
+
+NoErrorCode:
+ ;
+ ; Push a dummy error code on the stack
+ ; to maintain coherent stack map
+ ;
+ push [esp]
+ mov dword ptr [esp + 4], 0
+@@:
+ push ebp
+ mov ebp, esp
+
+ ;
+ ; Align stack to make sure that EFI_FX_SAVE_STATE_IA32 of EFI_SYSTEM_CONTEXT_IA32
+ ; is 16-byte aligned
+ ;
+ and esp, 0fffffff0h
+ sub esp, 12
+
+;; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
+ push dword ptr [ebp + 4] ; EAX
+ push ecx
+ push edx
+ push ebx
+ lea ecx, [ebp + 24]
+ push ecx ; ESP
+ push dword ptr [ebp] ; EBP
+ push esi
+ push edi
+
+ mov [ebp + 4], eax ; save vector number
+
+;; UINT32 Gs, Fs, Es, Ds, Cs, Ss;
+ mov eax, ss
+ push eax
+ movzx eax, word ptr [ebp + 16]
+ push eax
+ mov eax, ds
+ push eax
+ mov eax, es
+ push eax
+ mov eax, fs
+ push eax
+ mov eax, gs
+ push eax
+
+;; UINT32 Eip;
+ push dword ptr [ebp + 12]
+
+;; UINT32 Gdtr[2], Idtr[2];
+ sub esp, 8
+ sidt fword ptr [esp]
+ sub esp, 8
+ sgdt fword ptr [esp]
+
+;; UINT32 Ldtr, Tr;
+ xor eax, eax
+ str ax
+ push eax
+ sldt ax
+ push eax
+
+;; UINT32 EFlags;
+ push dword ptr [ebp + 20]
+
+;; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;
+ mov eax, cr4
+ or eax, 208h
+ mov cr4, eax
+ push eax
+ mov eax, cr3
+ push eax
+ mov eax, cr2
+ push eax
+ xor eax, eax
+ push eax
+ mov eax, cr0
+ push eax
+
+;; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
+ mov eax, dr7
+ push eax
+;; clear Dr7 while executing debugger itself
+ xor eax, eax
+ mov dr7, eax
+
+ mov eax, dr6
+ push eax
+;; insure all status bits in dr6 are clear...
+ xor eax, eax
+ mov dr6, eax
+
+ mov eax, dr3
+ push eax
+ mov eax, dr2
+ push eax
+ mov eax, dr1
+ push eax
+ mov eax, dr0
+ push eax
+
+;; FX_SAVE_STATE_IA32 FxSaveState;
+ sub esp, 512
+ mov edi, esp
+ db 0fh, 0aeh, 00000111y ;fxsave [edi]
+
+;; UINT32 ExceptionData;
+ push dword ptr [ebp + 8]
+
+;; call into exception handler
+ mov ebx, [ebp + 4]
+ mov eax, ExternalVectorTablePtr
+ mov eax, [eax + ebx * 4]
+ or eax, eax ; NULL?
+ je nonNullValue;
+
+;; Prepare parameter and call
+ mov edx, esp
+ push edx
+ push ebx
+ call eax
+ add esp, 8
+
+nonNullValue:
+ cli
+;; UINT32 ExceptionData;
+ add esp, 4
+
+;; FX_SAVE_STATE_IA32 FxSaveState;
+ mov esi, esp
+ db 0fh, 0aeh, 00001110y ; fxrstor [esi]
+ add esp, 512
+
+;; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
+ pop eax
+ mov dr0, eax
+ pop eax
+ mov dr1, eax
+ pop eax
+ mov dr2, eax
+ pop eax
+ mov dr3, eax
+;; skip restore of dr6. We cleared dr6 during the context save.
+ add esp, 4
+ pop eax
+ mov dr7, eax
+
+;; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;
+ pop eax
+ mov cr0, eax
+ add esp, 4 ; not for Cr1
+ pop eax
+ mov cr2, eax
+ pop eax
+ mov cr3, eax
+ pop eax
+ mov cr4, eax
+
+;; UINT32 EFlags;
+ pop dword ptr [ebp + 20]
+
+;; UINT32 Ldtr, Tr;
+;; UINT32 Gdtr[2], Idtr[2];
+;; Best not let anyone mess with these particular registers...
+ add esp, 24
+
+;; UINT32 Eip;
+ pop dword ptr [ebp + 12]
+
+;; UINT32 Gs, Fs, Es, Ds, Cs, Ss;
+;; NOTE - modified segment registers could hang the debugger... We
+;; could attempt to insulate ourselves against this possibility,
+;; but that poses risks as well.
+;;
+ pop gs
+ pop fs
+ pop es
+ pop ds
+ pop dword ptr [ebp + 16]
+ pop ss
+
+;; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
+ pop edi
+ pop esi
+ add esp, 4 ; not for ebp
+ add esp, 4 ; not for esp
+ pop ebx
+ pop edx
+ pop ecx
+ pop eax
+
+ mov esp, ebp
+ pop ebp
+ add esp, 8
+ iretd
+
+
+;---------------------------------------;
+; _GetTemplateAddressMap ;
+;----------------------------------------------------------------------------;
+;
+; Protocol prototype
+; GetTemplateAddressMap (
+; INTERRUPT_HANDLER_TEMPLATE_MAP *AddressMap
+; );
+;
+; Routine Description:
+;
+; Return address map of interrupt handler template so that C code can generate
+; interrupt handlers, and dynamically do address fix.
+;
+; Arguments:
+;
+;
+; Returns:
+;
+; Nothing
+;
+;
+; Input: [ebp][0] = Original ebp
+; [ebp][4] = Return address
+;
+; Output: Nothing
+;
+; Destroys: Nothing
+;-----------------------------------------------------------------------------;
+_GetTemplateAddressMap proc near public
+ push ebp ; C prolog
+ mov ebp, esp
+ pushad
+
+ mov ebx, dword ptr [ebp+08h]
+ mov dword ptr [ebx], TemplateStart
+ mov dword ptr [ebx+4h], TemplateEnd - TemplateStart
+
+ ; if code in Template is updated, the value fills into the 3rd parameter
+ ; also needs update
+ mov dword ptr [ebx+8h], VectorNumber - TemplateStart
+
+ popad
+ pop ebp
+ ret
+_GetTemplateAddressMap endp
+
+
+
+;---------------------------------------;
+; _InitializeSelectors ;
+;----------------------------------------------------------------------------;
+;
+; Protocol prototype
+; InitializeSelectors (
+; )
+;
+; Routine Description:
+;
+; Creates an new GDT in RAM. The problem is that our former selectors
+; were ROM based and the EFI OS Loader does not manipulate the machine state
+; to change them (as it would for a 16-bit PC/AT startup code that had to
+; go from Real Mode to flat mode).
+;
+; Arguments:
+;
+;
+; Returns:
+;
+; Nothing
+;
+;
+; Input: [ebp][0] = Original ebp
+; [ebp][4] = Return address
+;
+; Output: Nothing
+;
+; Destroys: Nothing
+;-----------------------------------------------------------------------------;
+
+CODE_SELECTOR EQU 10h
+DATA_SELECTOR EQU 18h
+
+_InitializeSelectors proc near public
+ push ebp ; C prolog
+ mov ebp, esp
+ pushad
+ mov edi, OFFSET Gdtr ; Load GDT register
+
+ mov ax,cs ; Get the selector data from our code image
+ mov es,ax
+ lgdt FWORD PTR es:[edi] ; and update the GDTR
+
+ db 067h
+ db 0eah ; Far Jump Offset:Selector to reload CS
+ dd OFFSET SelectorRld; Offset is ensuing instruction boundary
+ dw CODE_SELECTOR ; Selector is our code selector, 10h
+SelectorRld::
+ mov ax, DATA_SELECTOR ; Update the Base for the new selectors, too
+ mov ds, ax
+ mov es, ax
+ mov fs, ax
+ mov gs, ax
+ mov ss, ax
+
+ popad
+ pop ebp
+ ret
+_InitializeSelectors endp
+
+;------------------------------------------------------------------------------
+; VOID
+; CpuEnableInterrupt (
+; VOID
+; )
+;------------------------------------------------------------------------------
+CpuEnableInterrupt PROC C PUBLIC
+ sti
+ ret
+CpuEnableInterrupt ENDP
+
+
+;------------------------------------------------------------------------------
+; VOID
+; CpuDisableInterrupt (
+; VOID
+; )
+;------------------------------------------------------------------------------
+CpuDisableInterrupt PROC C PUBLIC
+ cli
+ ret
+CpuDisableInterrupt ENDP
+
+;------------------------------------------------------------------------------
+; VOID
+; CpuInitFloatPointUnit (
+; VOID
+; )
+;------------------------------------------------------------------------------
+CpuInitFloatPointUnit PROC C PUBLIC
+ finit
+ ret
+CpuInitFloatPointUnit ENDP
+
+;------------------------------------------------------------------------------
+; UINT16
+; GetCodeSegment (
+; VOID
+; )
+;------------------------------------------------------------------------------
+GetCodeSegment PROC C PUBLIC
+ mov ax,cs
+ ret
+GetCodeSegment ENDP
+
+
+;------------------------------------------------------------------------------
+; VOID
+; EfiWbinvd (
+; VOID
+; )
+;------------------------------------------------------------------------------
+EfiWbinvd PROC PUBLIC
+ wbinvd
+ ret
+EfiWbinvd ENDP
+
+
+;------------------------------------------------------------------------------
+; VOID
+; EfiInvd (
+; VOID
+; )
+;------------------------------------------------------------------------------
+EfiInvd PROC PUBLIC
+ invd
+ ret
+EfiInvd ENDP
+
+;------------------------------------------------------------------------------
+; VOID
+; GetIdt (
+; IDT_INFORMATION *IdtInfo
+; )
+;------------------------------------------------------------------------------
+_GetIdt proc near public
+ push ebp ; C prolog
+
+ mov ebp, esp
+ mov eax, [ebp+8]
+ sidt FWORD PTR [eax]
+
+ pop ebp
+ ret
+_GetIdt ENDP
+
+GetCoreNumber PROC C PUBLIC
+
+ push ebx
+
+ mov eax, 4
+ mov ecx, 0
+ cpuid
+
+ shr eax, 26
+ and eax, 3fh
+ inc al
+
+ pop ebx
+
+ ret
+
+GetCoreNumber ENDP
+
+
+;-----------------------------------------------------------------------------;
+; data
+;-----------------------------------------------------------------------------;
+
+ align 16
+
+gdtr dw GDT_END - GDT_BASE - 1 ; GDT limit
+ dd OFFSET GDT_BASE ; (GDT base gets set above)
+
+;-----------------------------------------------------------------------------;
+; global descriptor table (GDT)
+;-----------------------------------------------------------------------------;
+
+ align 16
+
+public GDT_BASE
+GDT_BASE:
+; null descriptor
+NULL_SEL equ $-GDT_BASE ; Selector [0]
+ dw 0 ; limit 15:0
+ dw 0 ; base 15:0
+ db 0 ; base 23:16
+ db 0 ; type
+ db 0 ; limit 19:16, flags
+ db 0 ; base 31:24
+
+; linear data segment descriptor
+LINEAR_SEL equ $-GDT_BASE ; Selector [0x8]
+ dw 0FFFFh ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 092h ; present, ring 0, data, expand-up, writable
+ db 0CFh ; page-granular, 32-bit
+ db 0
+
+; linear code segment descriptor
+LINEAR_CODE_SEL equ $-GDT_BASE ; Selector [0x10]
+ dw 0FFFFh ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 09Ah ; present, ring 0, data, expand-up, writable
+ db 0CFh ; page-granular, 32-bit
+ db 0
+
+; system data segment descriptor
+SYS_DATA_SEL equ $-GDT_BASE ; Selector [0x18]
+ dw 0FFFFh ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 092h ; present, ring 0, data, expand-up, writable
+ db 0CFh ; page-granular, 32-bit
+ db 0
+
+; system code segment descriptor
+SYS_CODE_SEL equ $-GDT_BASE
+ dw 0FFFFh ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 09Ah ; present, ring 0, data, expand-up, writable
+ db 0CFh ; page-granular, 32-bit
+ db 0
+
+; spare segment descriptor
+SPARE3_SEL equ $-GDT_BASE
+ dw 0 ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 0 ; present, ring 0, data, expand-up, writable
+ db 0 ; page-granular, 32-bit
+ db 0
+
+; spare segment descriptor
+SPARE4_SEL equ $-GDT_BASE
+ dw 0 ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 0 ; present, ring 0, data, expand-up, writable
+ db 0 ; page-granular, 32-bit
+ db 0
+
+; spare segment descriptor
+SPARE5_SEL equ $-GDT_BASE
+ dw 0 ; limit 0xFFFFF
+ dw 0 ; base 0
+ db 0
+ db 0 ; present, ring 0, data, expand-up, writable
+ db 0 ; page-granular, 32-bit
+ db 0
+
+GDT_END:
+
+
+ end
+
diff --git a/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/Ia32/CpuAsm.s b/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/Ia32/CpuAsm.s
new file mode 100644
index 0000000000..9b62ca1688
--- /dev/null
+++ b/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/Ia32/CpuAsm.s
@@ -0,0 +1,761 @@
+## @file
+# Assembly code that supports IA32 CPU architectural protocol.
+#
+# Copyright (c) 1999 - 2015, 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
+#
+##
+
+.data
+
+ExternalVectorTablePtr: .space 4
+CommonInterruptEntry: .long CommonEntry
+Idtr: .space 2
+Idtr1: .space 4
+
+##include Htequ.inc
+
+.equ VacantFlag , 0x00
+.equ NotVacantFlag , 0xff
+.equ StartupApSignal , 0x6E750000
+.equ MonitorFilterSize, 0x10
+.equ ApCounterInit , 0
+.equ ApInHltLoop , 1
+.equ ApInMwaitLoop , 2
+.equ ApInRunLoop , 3
+
+.equ LockLocation , 0x1000 - 0x0400
+.equ StackStart , LockLocation + 0x4
+.equ StackSize , LockLocation + 0x8
+.equ RendezvousProc , LockLocation + 0x0C
+.equ GdtrProfile , LockLocation + 0x10
+.equ IdtrProfile , LockLocation + 0x16
+.equ BufferStart , LockLocation + 0x1C
+.equ Cr3Location , LockLocation + 0x20
+.equ InitFlag , LockLocation + 0x24
+.equ WakeUpApManner , LockLocation + 0x28
+.equ BistBuffer , LockLocation + 0x2C
+
+.macro PAUSE32
+ .byte 0xF3
+ .byte 0x90
+.endm
+
+.text
+
+#---------------------------------------#
+# _InitializeIdt #
+#----------------------------------------------------------------------------#
+#
+# Protocol prototype
+# InitializeIdt (
+# IN EFI_CPU_INTERRUPT_HANDLER TableStart,
+# IN UINTN *IdtTablePtr,
+# IN UINT16 IdtLimit
+# )
+#
+# Routine Description:
+#
+# Creates an IDT table starting at IdtTablPtr. It has IdtLimit/8 entries.
+# Table is initialized to intxx where xx is from 00 to number of entries or
+# 100h, whichever is smaller. After table has been initialized the LIDT
+# instruction is invoked.
+#
+# TableStart is the pointer to the callback table and is not used by
+# InitializedIdt but by commonEntry. CommonEntry handles all interrupts,
+# does the context save and calls the callback entry, if non-NULL.
+# It is the responsibility of the callback routine to do hardware EOIs.
+#
+# Arguments:
+#
+# TableStart - Pointer to interrupt callback table
+#
+# IdtTablePtr - Pointer to IDT table
+#
+# IdtLimit - IDT Table limit = number of interrupt entries * 8
+#
+# Returns:
+#
+# Nothing
+#
+#
+# Input: [ebp][0] = Original ebp
+# [ebp][4] = Return address
+# [ebp][8] = TableStart
+# [ebp][0c] = *IdtTablePtr
+# [ebp][10] = IdtLimit
+#
+# Output: Nothing
+#
+# Destroys: Nothing
+#-----------------------------------------------------------------------------#
+
+ASM_GLOBAL ASM_PFX(InitializeIdt)
+ASM_PFX(InitializeIdt):
+ pushl %ebp # C prolog
+ movl %esp,%ebp
+ pushl %edi
+
+ movl 8(%ebp),%eax # Get ExternalVectorTable Address
+ movl %eax, ExternalVectorTablePtr
+
+ movw 0x10(%ebp),%ax # Get IDT Table limit
+ decw %ax
+ movw %ax, Idtr # Store %ax to Idtr
+
+ movl 0xc(%ebp),%eax # Get Start of IDT
+ movl %eax, Idtr1
+
+ movl $Idtr, %edi # Addr of Idtr -> %edi
+ lidt %es:(%edi)
+
+ popl %edi
+ popl %ebp
+ ret
+
+#----------------------------------------------------------------------------#
+#
+# Protocol prototype
+# None
+#
+# Routine Description:
+#
+# These routines handle the individual interrupts. These routines always
+# gain control on any interrupt or exception. They save EAX and place
+# the interrupt number in EAX. CommonEntry is then jumped to.
+# instruction is invoked.
+#
+# CommonEntry handles all interrupts,does the context save and calls the
+# callback entry, if non-NULL. It is the responsibility of the callback
+# routine to do hardware EOIs. Callbacks are entered into the table
+# located at TableStart. Entries are modified by the InstallInterruptHandler
+# and UninstallInterruptHandler protocols.
+#
+# Arguments to CommonEntry:
+#
+# EAX - Interrupt or exception number
+#
+# TableStart - Pointer to interrupt callback table
+#
+# Returns:
+#
+# Nothing
+#
+#
+# Output: Nothing
+#
+# Destroys: Nothing
+#-----------------------------------------------------------------------------#
+
+TemplateStart:
+ pushl %eax
+
+ #mov eax, 0nnh (nn stands for vector number, which will be fixed at runtime
+ .byte 0xb8
+VectorNumber:
+ .long 0x0
+
+ jmp *CommonInterruptEntry
+TemplateEnd:
+
+CommonEntry:
+
+#---------------------------------------#
+# _CommonEntry #
+#----------------------------------------------------------------------------#
+# The follow algorithm is used for the common interrupt routine.
+# Entry from each interrupt with a push eax and eax=interrupt number
+
+#
+# +---------------------+
+# + EFlags +
+# +---------------------+
+# + CS +
+# +---------------------+
+# + EIP +
+# +---------------------+
+# + Error Code +
+# +---------------------+
+# + EAX / Vector Number +
+# +---------------------+
+# + EBP +
+# +---------------------+ <-- EBP
+#
+
+ cli
+ #
+ # All interrupt handlers are invoked through interrupt gates, so
+ # IF flag automatically cleared at the entry point
+ #
+ cmpl $32,%eax # Intel reserved vector for exceptions?
+ jae NoErrorCode
+ btl %eax, %cs:ASM_PFX(mErrorCodeFlag)
+ jc L1
+
+NoErrorCode:
+ #
+ # Push a dummy error code on the stack
+ # to maintain coherent stack map
+ #
+ pushl (%esp) # Push the value %esp pointing to
+ movl $0, 4(%esp)
+L1:
+ pushl %ebp
+ movl %esp,%ebp
+
+ #
+ # Align stack to make sure that EFI_FX_SAVE_STATE_IA32 of EFI_SYSTEM_CONTEXT_IA32
+ # is 16-byte aligned
+ #
+ andl $0xfffffff0,%esp
+ subl $12,%esp
+
+## UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax#
+ pushl 0x4(%ebp)
+ pushl %ecx
+ pushl %edx
+ pushl %ebx
+ leal 24(%ebp),%ecx
+ pushl %ecx # ESP
+ pushl (%ebp)
+ pushl %esi
+ pushl %edi
+
+ movl %eax,4(%ebp) # save vector number
+
+## UINT32 Gs, Fs, Es, Ds, Cs, Ss#
+ movl %ss,%eax
+ pushl %eax
+ movzwl 16(%ebp), %eax
+ pushl %eax
+ movl %ds,%eax
+ pushl %eax
+ movl %es,%eax
+ pushl %eax
+ movl %fs,%eax
+ pushl %eax
+ movl %gs,%eax
+ pushl %eax
+
+## UINT32 Eip#
+ pushl 12(%ebp)
+
+## UINT32 Gdtr[2], Idtr[2]#
+ subl $8,%esp
+ sidt (%esp)
+ subl $8,%esp
+ sgdt (%esp)
+
+## UINT32 Ldtr, Tr#
+ xorl %eax,%eax
+ strl %eax
+ pushl %eax
+ sldtl %eax
+ pushl %eax
+
+## UINT32 EFlags#
+ pushl 20(%ebp)
+
+## UINT32 Cr0, Cr1, Cr2, Cr3, Cr4#
+ movl %cr4, %eax
+ orl $0x208,%eax
+ movl %eax, %cr4
+ pushl %eax
+ movl %cr3, %eax
+ pushl %eax
+ movl %cr2, %eax
+ pushl %eax
+ xorl %eax,%eax
+ pushl %eax
+ movl %cr0, %eax
+ pushl %eax
+
+## UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7#
+ movl %dr7, %eax
+ pushl %eax
+## clear Dr7 while executing debugger itself
+ xorl %eax, %eax
+ movl %eax, %dr7
+
+ movl %dr6, %eax
+ pushl %eax
+## insure all status bits in dr6 are clear...
+ xorl %eax, %eax
+ movl %eax, %dr6
+
+ movl %dr3, %eax
+ pushl %eax
+ movl %dr2, %eax
+ pushl %eax
+ movl %dr1, %eax
+ pushl %eax
+ movl %dr0, %eax
+ pushl %eax
+
+## FX_SAVE_STATE_IA32 FxSaveState#
+ subl $512, %esp
+ movl %esp, %edi
+ .byte 0x0f, 0xae, 0x07
+
+## UEFI calling convention for IA32 requires that Direction flag in EFLAGs is clear
+ cld
+
+## UINT32 ExceptionData#
+ pushl 8(%ebp)
+
+## call into exception handler
+ movl 4(%ebp), %ebx
+ movl ExternalVectorTablePtr, %eax
+ movl (%eax,%ebx,4), %eax
+ orl %eax, %eax # NULL?
+ je nonNullValue #
+
+## Prepare parameter and call
+ movl %esp, %edx
+ pushl %edx
+ pushl %ebx
+ call *%eax
+ addl $8, %esp
+
+nonNullValue:
+ cli
+
+## UINT32 ExceptionData#
+ addl $4,%esp
+
+## FX_SAVE_STATE_IA32 FxSaveState#
+ movl %esp, %esi
+ .byte 0x0f, 0xae, 0x0e
+ addl $512, %esp
+
+## UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7#
+ popl %eax
+ movl %eax, %dr0
+ popl %eax
+ movl %eax, %dr1
+ popl %eax
+ movl %eax, %dr2
+ popl %eax
+ movl %eax, %dr3
+## skip restore of dr6. We cleared dr6 during the context save.
+ addl $4, %esp
+ popl %eax
+ movl %eax, %dr7
+
+## UINT32 Cr0, Cr1, Cr2, Cr3, Cr4#
+ popl %eax
+ movl %eax, %cr0
+ addl $4,%esp # not for Cr1
+ popl %eax
+ movl %eax, %cr2
+ popl %eax
+ movl %eax, %cr3
+ popl %eax
+ movl %eax, %cr4
+
+## UINT32 EFlags#
+ popl 20(%ebp)
+
+## UINT32 Ldtr, Tr#
+## UINT32 Gdtr[2], Idtr[2]#
+## Best not let anyone mess with these particular registers...
+ addl $24,%esp
+
+## UINT32 Eip#
+ pop 12(%ebp)
+
+## UINT32 Gs, Fs, Es, Ds, Cs, Ss#
+## NOTE - modified segment registers could hang the debugger... We
+## could attempt to insulate ourselves against this possibility,
+## but that poses risks as well.
+##
+ popl %gs
+ popl %fs
+ popl %es
+ popl %ds
+ popl 16(%ebp)
+ popl %ss
+
+## UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax#
+ popl %edi
+ popl %esi
+ addl $4, %esp # not for ebp
+ addl $4, %esp # not for esp
+ popl %ebx
+ popl %edx
+ popl %ecx
+ popl %eax
+
+ movl %ebp, %esp
+ popl %ebp
+ addl $8,%esp
+ iretl
+
+
+#---------------------------------------#
+# _GetTemplateAddressMap #
+#----------------------------------------------------------------------------#
+#
+# Protocol prototype
+# GetTemplateAddressMap (
+# INTERRUPT_HANDLER_TEMPLATE_MAP *AddressMap
+# )#
+#
+# Routine Description:
+#
+# Return address map of interrupt handler template so that C code can generate
+# interrupt handlers, and dynamically do address fix.
+#
+# Arguments:
+#
+#
+# Returns:
+#
+# Nothing
+#
+#
+# Input: [ebp][0] = Original ebp
+# [ebp][4] = Return address
+#
+# Output: Nothing
+#
+# Destroys: Nothing
+#-----------------------------------------------------------------------------#
+ASM_GLOBAL ASM_PFX(GetTemplateAddressMap)
+ASM_PFX(GetTemplateAddressMap):
+ pushl %ebp # C prolog
+ movl %esp,%ebp
+ pushal
+
+ movl 8(%ebp), %ebx
+ movl $TemplateStart, (%ebx)
+ movl $(TemplateEnd - TemplateStart), 4(%ebx)
+
+ # Note: if code in Template is updated, the value fills into the 3rd parameter
+ # also needs update
+ movl $(VectorNumber - TemplateStart), 8(%ebx)
+
+ popal
+ popl %ebp
+ ret
+
+
+
+#---------------------------------------#
+# _InitializeSelectors #
+#----------------------------------------------------------------------------#
+#
+# Protocol prototype
+# InitializeSelectors (
+# )
+#
+# Routine Description:
+#
+# Creates an new GDT in RAM. The problem is that our former selectors
+# were ROM based and the EFI OS Loader does not manipulate the machine state
+# to change them (as it would for a 16-bit PC/AT startup code that had to
+# go from Real Mode to flat mode).
+#
+# Arguments:
+#
+#
+# Returns:
+#
+# Nothing
+#
+#
+# Input: [ebp][0] = Original ebp
+# [ebp][4] = Return address
+#
+# Output: Nothing
+#
+# Destroys: Nothing
+#-----------------------------------------------------------------------------#
+
+.equ CODE_SELECTOR, 0x10
+.equ DATA_SELECTOR, 0x18
+
+ASM_GLOBAL ASM_PFX(InitializeSelectors)
+ASM_PFX(InitializeSelectors):
+ pushl %ebp # C prolog
+ movl %esp,%ebp
+ pushal
+ movl $Gdtr, %edi
+
+ movw %cs,%ax # Get the selector data from our code image
+ .byte 0x66
+ movw %ax,%es
+ lgdt %es:(%edi)
+
+ .byte 0x67
+ .byte 0xea # Far Jump Offset:Selector to reload CS
+ .long SelectorRld
+ .word CODE_SELECTOR
+SelectorRld:
+ movw $DATA_SELECTOR, %ax # Update the Base for the new selectors, too
+ .byte 0x66
+ movw %ax,%ds
+ .byte 0x66
+ movw %ax,%es
+ .byte 0x66
+ movw %ax,%fs
+ .byte 0x66
+ movw %ax,%gs
+ .byte 0x66
+ movw %ax,%ss
+
+ popal
+ popl %ebp
+ ret
+
+#------------------------------------------------------------------------------
+# VOID
+# CpuEnableInterrupt (
+# VOID
+# )
+#------------------------------------------------------------------------------
+ASM_GLOBAL ASM_PFX(CpuEnableInterrupt)
+ASM_PFX(CpuEnableInterrupt):
+ sti
+ ret
+#CpuEnableInterrupt ENDP
+
+
+#------------------------------------------------------------------------------
+# VOID
+# CpuDisableInterrupt (
+# VOID
+# )
+#------------------------------------------------------------------------------
+ASM_GLOBAL ASM_PFX(CpuDisableInterrupt)
+ASM_PFX(CpuDisableInterrupt):
+ cli
+ ret
+#CpuDisableInterrupt ENDP
+
+#------------------------------------------------------------------------------
+# VOID
+# CpuInitFloatPointUnit (
+# VOID
+# )
+#------------------------------------------------------------------------------
+ASM_GLOBAL ASM_PFX(CpuInitFloatPointUnit)
+ASM_PFX(CpuInitFloatPointUnit):
+ finit
+ ret
+#CpuInitFloatPointUnit ENDP
+
+#------------------------------------------------------------------------------
+# UINT16
+# GetCodeSegment (
+# VOID
+# )
+#------------------------------------------------------------------------------
+ASM_GLOBAL ASM_PFX(GetCodeSegment)
+ASM_PFX(GetCodeSegment):
+ movw %cs, %ax
+ ret
+#GetCodeSegment ENDP
+
+
+#------------------------------------------------------------------------------
+# VOID
+# EfiWbinvd (
+# VOID
+# )
+#------------------------------------------------------------------------------
+ASM_GLOBAL ASM_PFX(EfiWbinvd)
+ASM_PFX(EfiWbinvd):
+ wbinvd
+ ret
+#EfiWbinvd ENDP
+
+#------------------------------------------------------------------------------
+# VOID
+# EfiInvd (
+# VOID
+# )
+#------------------------------------------------------------------------------
+ASM_GLOBAL ASM_PFX(EfiInvd)
+ASM_PFX(EfiInvd):
+ invd
+ ret
+#EfiInvd ENDP
+
+#------------------------------------------------------------------------------
+# VOID
+# GetIdt (
+# IDT_INFORMATION *IdtInfo
+# )
+#------------------------------------------------------------------------------
+ASM_GLOBAL ASM_PFX(GetIdt)
+ASM_PFX(GetIdt):
+ push %ebp # C prolog
+
+ movl %esp, %ebp
+ movl 8(%ebp), %eax
+ sidt (%eax)
+
+ popl %ebp
+ ret
+#GetIdt ENDP
+
+#------------------------------------------------------------------------------
+# VOID
+# C1eExceptionHandler (
+# VOID
+# )
+#------------------------------------------------------------------------------
+ASM_GLOBAL ASM_PFX(C1eExceptionHandler)
+ASM_PFX(C1eExceptionHandler):
+ pushl %ebp # C prolog
+ movl %esp, %ebp
+ pushfl
+ cli
+ pushal
+
+ # Verify if GPE was caused by C1e write.
+ # If not, pass control to real exception handler.
+ cmp $0, ASM_PFX(mWroteMsr)
+ je notourexception
+
+ # Fix the return address on stack to skip offending
+ # code which caused the exception.
+ movl 8(%ebp), %eax
+ addl $2, %eax
+ movl %eax, 8(%ebp)
+ jmp exit
+
+notourexception:
+ popal
+ popfl
+ popl %ebp
+
+ jmp ASM_PFX(mOriginalInt13)
+
+exit:
+
+ popal
+ popfl
+ popl %ebp
+ addl $4, %esp
+ iretl
+#C1eExceptionHandler ENDP
+
+
+ASM_GLOBAL ASM_PFX(GetCoreNumber)
+ASM_PFX(GetCoreNumber):
+
+ pushl %ebx
+
+ movl $4, %eax
+ movl $0, %ecx
+ cpuid
+
+ shrl $26, %eax
+ andl $0x3f, %eax
+ incb %al
+
+ popl %ebx
+
+ ret
+
+#GetCoreNumber ENDP
+
+#-----------------------------------------------------------------------------#
+# data
+#-----------------------------------------------------------------------------#
+
+ .p2align 4
+
+Gdtr: .word GDT_END - GDT_BASE - 1
+ .long GDT_BASE
+
+#-----------------------------------------------------------------------------#
+# global descriptor table (GDT)
+#-----------------------------------------------------------------------------#
+
+ .p2align 4
+
+GDT_BASE:
+# null descriptor
+# .equ NULL_SEL, $-GDT_BASE # Selector [0]
+ .word 0 # limit 15:0
+ .word 0 # base 15:0
+ .byte 0 # base 23:16
+ .byte 0 # type
+ .byte 0 # limit 19:16, flags
+ .byte 0 # base 31:24
+
+# linear data segment descriptor
+# .equ LINEAR_SEL, $-GDT_BASE # Selector [0x8]
+ .word 0xFFFF # limit 0xFFFFF
+ .word 0 # base 0
+ .byte 0
+ .byte 0x92 # present, ring 0, data, expand-up, writable
+ .byte 0xCF # page-granular, 32-bit
+ .byte 0
+
+# linear code segment descriptor
+# .equ LINEAR_CODE_SEL, $-GDT_BASE # Selector [0x10]
+ .word 0xFFFF # limit 0xFFFFF
+ .word 0 # base 0
+ .byte 0
+ .byte 0x9A # present, ring 0, data, expand-up, writable
+ .byte 0xCF # page-granular, 32-bit
+ .byte 0
+
+# system data segment descriptor
+# .equ SYS_DATA_SEL, $-GDT_BASE # Selector [0x18]
+ .word 0xFFFF # limit 0xFFFFF
+ .word 0 # base 0
+ .byte 0
+ .byte 0x92 # present, ring 0, data, expand-up, writable
+ .byte 0xCF # page-granular, 32-bit
+ .byte 0
+
+# system code segment descriptor
+# .equ SYS_CODE_SEL, $-GDT_BASE
+ .word 0xFFFF # limit 0xFFFFF
+ .word 0 # base 0
+ .byte 0
+ .byte 0x9A # present, ring 0, data, expand-up, writable
+ .byte 0xCF # page-granular, 32-bit
+ .byte 0
+
+# spare segment descriptor
+# .equ SPARE3_SEL, $-GDT_BASE
+ .word 0 # limit 0xFFFFF
+ .word 0 # base 0
+ .byte 0
+ .byte 0 # present, ring 0, data, expand-up, writable
+ .byte 0 # page-granular, 32-bit
+ .byte 0
+
+# spare segment descriptor
+# .equ SPARE4_SEL, $-GDT_BASE
+ .word 0 # limit 0xFFFFF
+ .word 0 # base 0
+ .byte 0
+ .byte 0 # present, ring 0, data, expand-up, writable
+ .byte 0 # page-granular, 32-bit
+ .byte 0
+
+# spare segment descriptor
+# .equ SPARE5_SEL, $-GDT_BASE
+ .word 0 # limit 0xFFFFF
+ .word 0 # base 0
+ .byte 0
+ .byte 0 # present, ring 0, data, expand-up, writable
+ .byte 0 # page-granular, 32-bit
+ .byte 0
+
+GDT_END:
+
diff --git a/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/Ia32/Exception.c b/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/Ia32/Exception.c
new file mode 100644
index 0000000000..89734ddfe2
--- /dev/null
+++ b/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/Ia32/Exception.c
@@ -0,0 +1,337 @@
+/** @file
+ IA-32 Exception Handler.
+
+ Copyright (c) 1999 - 2015, 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 "CpuDxe.h"
+#include "MpCommon.h"
+#include "Exception.h"
+
+typedef
+VOID
+(*EFI_INSTALL_EXCEPTION) (
+ IN UINT32 InterruptType,
+ IN VOID *SystemContext
+ );
+/**
+ @todo No description
+
+**/
+typedef struct {
+ UINT32 ErrorMessage;
+ UINT8 Interrupt;
+} EFI_EXCEPTION_HANDLER;
+
+//
+// Error code flag indicating whether or not an error code will be
+// pushed on the stack if an exception occurs.
+//
+// 1 means an error code will be pushed, otherwise 0
+//
+// bit 0 - exception 0
+// bit 1 - exception 1
+// etc.
+//
+UINT32 mErrorCodeFlag = 0x00027d00;
+
+//
+// Local Table
+//
+EFI_EXCEPTION_HANDLER mExceptionTable[] = {
+ {
+ EFI_SW_EC_IA32_DIVIDE_ERROR,
+ INTERRUPT_HANDLER_DIVIDE_ZERO
+ },
+ {
+ EFI_SW_EC_IA32_DEBUG,
+ INTERRUPT_HANDLER_DEBUG
+ },
+ {
+ EFI_SW_EC_IA32_NMI,
+ INTERRUPT_HANDLER_NMI
+ },
+ {
+ EFI_SW_EC_IA32_BREAKPOINT,
+ INTERRUPT_HANDLER_BREAKPOINT
+ },
+ {
+ EFI_SW_EC_IA32_OVERFLOW,
+ INTERRUPT_HANDLER_OVERFLOW
+ },
+ {
+ EFI_SW_EC_IA32_BOUND,
+ INTERRUPT_HANDLER_BOUND
+ },
+ {
+ EFI_SW_EC_IA32_INVALID_OPCODE,
+ INTERRUPT_HANDLER_INVALID_OPCODE
+ },
+ //
+ // Interrupt 7, 9, 15 not defined in the debug support protocol. Hence no status codes for them!
+ //
+ {
+ EFI_SW_EC_IA32_DOUBLE_FAULT,
+ INTERRUPT_HANDLER_DOUBLE_FAULT
+ },
+ {
+ EFI_SW_EC_IA32_INVALID_TSS,
+ INTERRUPT_HANDLER_INVALID_TSS
+ },
+ {
+ EFI_SW_EC_IA32_SEG_NOT_PRESENT,
+ INTERRUPT_HANDLER_SEGMENT_NOT_PRESENT
+ },
+ {
+ EFI_SW_EC_IA32_STACK_FAULT,
+ INTERRUPT_HANDLER_STACK_SEGMENT_FAULT
+ },
+ {
+ EFI_SW_EC_IA32_GP_FAULT,
+ INTERRUPT_HANDLER_GP_FAULT
+ },
+ {
+ EFI_SW_EC_IA32_PAGE_FAULT,
+ INTERRUPT_HANDLER_PAGE_FAULT
+ },
+ {
+ EFI_SW_EC_IA32_FP_ERROR,
+ INTERRUPT_HANDLER_MATH_FAULT
+ },
+ {
+ EFI_SW_EC_IA32_ALIGNMENT_CHECK,
+ INTERRUPT_HANDLER_ALIGNMENT_FAULT
+ },
+ {
+ EFI_SW_EC_IA32_MACHINE_CHECK,
+ INTERRUPT_HANDLER_MACHINE_CHECK
+ },
+ {
+ EFI_SW_EC_IA32_SIMD,
+ INTERRUPT_HANDLER_STREAMING_SIMD
+ }
+};
+
+UINTN mExceptionNumber = sizeof (mExceptionTable) / sizeof (EFI_EXCEPTION_HANDLER);
+
+CPU_STATUS_CODE_TEMPLATE mStatusCodeData = {
+ {
+ sizeof (EFI_STATUS_CODE_DATA),
+ sizeof (EFI_SYSTEM_CONTEXT_IA32),
+ EFI_STATUS_CODE_DATA_TYPE_EXCEPTION_HANDLER_GUID
+ },
+ {
+ 0
+ }
+};
+
+/**
+ Report StatusCode for Exception
+
+ @param[in] InterruptType Interrupt type
+ @param[in] SystemContext EFI_SYSTEM_CONTEXT
+
+ @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+ReportData (
+ IN EFI_EXCEPTION_TYPE InterruptType,
+ IN EFI_SYSTEM_CONTEXT SystemContext
+ )
+{
+ UINT32 ErrorMessage;
+ UINT32 Index;
+
+ CopyMem (
+ &mStatusCodeData.SystemContext.SystemContextIa32,
+ SystemContext.SystemContextIa32,
+ sizeof (EFI_SYSTEM_CONTEXT_IA32)
+ );
+
+ ErrorMessage = EFI_SOFTWARE_DXE_BS_DRIVER;
+ for (Index = 0; Index < mExceptionNumber; Index++) {
+ if (mExceptionTable[Index].Interrupt == InterruptType) {
+ ErrorMessage |= mExceptionTable[Index].ErrorMessage;
+ break;
+ }
+ }
+
+ REPORT_STATUS_CODE_EX (
+ (EFI_ERROR_CODE | EFI_ERROR_UNRECOVERED),
+ EFI_SOFTWARE_UNSPECIFIED | ErrorMessage,
+ 0,
+ &gEfiCallerIdGuid,
+ NULL,
+ (EFI_STATUS_CODE_DATA *)&mStatusCodeData,
+ sizeof(CPU_STATUS_CODE_TEMPLATE)
+ );
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Common exception handler
+
+ @param[in] InterruptType Exception type
+ @param[in] SystemContext EFI_SYSTEM_CONTEXT
+**/
+VOID
+EFIAPI
+CommonExceptionHandler (
+ IN EFI_EXCEPTION_TYPE InterruptType,
+ IN EFI_SYSTEM_CONTEXT SystemContext
+ )
+{
+ DEBUG ((
+ EFI_D_ERROR,
+ "!!!! IA32 Exception Type - %08x !!!!\n",
+ InterruptType
+ ));
+ DEBUG ((
+ EFI_D_ERROR,
+ "EIP - %08x, CS - %08x, EFLAGS - %08x\n",
+ SystemContext.SystemContextIa32->Eip,
+ SystemContext.SystemContextIa32->Cs,
+ SystemContext.SystemContextIa32->Eflags
+ ));
+ if (mErrorCodeFlag & (1 << InterruptType)) {
+ DEBUG ((
+ EFI_D_ERROR,
+ "ExceptionData - %08x\n",
+ SystemContext.SystemContextIa32->ExceptionData
+ ));
+ }
+ DEBUG ((
+ EFI_D_ERROR,
+ "EAX - %08x, ECX - %08x, EDX - %08x, EBX - %08x\n",
+ SystemContext.SystemContextIa32->Eax,
+ SystemContext.SystemContextIa32->Ecx,
+ SystemContext.SystemContextIa32->Edx,
+ SystemContext.SystemContextIa32->Ebx
+ ));
+ DEBUG ((
+ EFI_D_ERROR,
+ "ESP - %08x, EBP - %08x, ESI - %08x, EDI - %08x\n",
+ SystemContext.SystemContextIa32->Esp,
+ SystemContext.SystemContextIa32->Ebp,
+ SystemContext.SystemContextIa32->Esi,
+ SystemContext.SystemContextIa32->Edi
+ ));
+ DEBUG ((
+ EFI_D_ERROR,
+ "DS - %08x, ES - %08x, FS - %08x, GS - %08x, SS - %08x\n",
+ SystemContext.SystemContextIa32->Ds,
+ SystemContext.SystemContextIa32->Es,
+ SystemContext.SystemContextIa32->Fs,
+ SystemContext.SystemContextIa32->Gs,
+ SystemContext.SystemContextIa32->Ss
+ ));
+ DEBUG ((
+ EFI_D_ERROR,
+ "GDTR - %08x %08x, IDTR - %08x %08x\n",
+ SystemContext.SystemContextIa32->Gdtr[0],
+ SystemContext.SystemContextIa32->Gdtr[1],
+ SystemContext.SystemContextIa32->Idtr[0],
+ SystemContext.SystemContextIa32->Idtr[1]
+ ));
+ DEBUG ((
+ EFI_D_ERROR,
+ "LDTR - %08x, TR - %08x\n",
+ SystemContext.SystemContextIa32->Ldtr,
+ SystemContext.SystemContextIa32->Tr
+ ));
+ DEBUG ((
+ EFI_D_ERROR,
+ "CR0 - %08x, CR2 - %08x, CR3 - %08x, CR4 - %08x\n",
+ SystemContext.SystemContextIa32->Cr0,
+ SystemContext.SystemContextIa32->Cr2,
+ SystemContext.SystemContextIa32->Cr3,
+ SystemContext.SystemContextIa32->Cr4
+ ));
+ DEBUG ((
+ EFI_D_ERROR,
+ "DR0 - %08x, DR1 - %08x, DR2 - %08x, DR3 - %08x\n",
+ SystemContext.SystemContextIa32->Dr0,
+ SystemContext.SystemContextIa32->Dr1,
+ SystemContext.SystemContextIa32->Dr2,
+ SystemContext.SystemContextIa32->Dr3
+ ));
+ DEBUG ((
+ EFI_D_ERROR,
+ "DR6 - %08x, DR7 - %08x\n",
+ SystemContext.SystemContextIa32->Dr6,
+ SystemContext.SystemContextIa32->Dr7
+ ));
+
+ //
+ // Report Status Code
+ //
+ ReportData (InterruptType, SystemContext);
+
+ //
+ // Use this macro to hang so that the compiler does not optimize out
+ // the following RET instructions. This allows us to return if we
+ // have a debugger attached.
+ //
+ CpuDeadLoop ();
+
+ return ;
+}
+
+/**
+ Install the IA-32 Exception Handler.
+ The current operation (which likely will change) will uninstall all the
+ pertinent exception handlers (0-7, 10-14, 16-19) except for Int8 which the timer
+ is currently sitting on (or soon will be).
+
+ It then installs all the appropriate handlers for each exception.
+
+ The handler then calls gRT->ReportStatusCode with a specific progress code. The
+ progress codes for now start at 0x200 for IA-32 processors. See Status Code
+ Specification for details. The Status code Specification uses the enumeration from
+ the EFI 1.1 Debug Support Protocol.
+
+ @param[in] *CpuProtocol Instance of CPU Arch Protocol
+
+ @retval EFI_STATUS
+
+**/
+EFI_STATUS
+InitializeException (
+ IN EFI_CPU_ARCH_PROTOCOL *CpuProtocol
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+
+ Status = CpuProtocol->DisableInterrupt (CpuProtocol);
+
+ for (Index = 0; Index < mExceptionNumber; Index++) {
+ Status = CpuProtocol->RegisterInterruptHandler (
+ CpuProtocol,
+ mExceptionTable[Index].Interrupt,
+ NULL
+ );
+
+ Status = CpuProtocol->RegisterInterruptHandler (
+ CpuProtocol,
+ mExceptionTable[Index].Interrupt,
+ CommonExceptionHandler
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ return Status;
+}
diff --git a/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/Ia32/Htequ.inc b/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/Ia32/Htequ.inc
new file mode 100644
index 0000000000..5554cefd42
--- /dev/null
+++ b/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/Ia32/Htequ.inc
@@ -0,0 +1,40 @@
+;; @file
+;
+; Copyright (c) 2010 - 2015, 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
+StartupApSignal Equ 6E750000h
+MonitorFilterSize Equ 10h
+ApCounterInit Equ 0
+ApInHltLoop Equ 1
+ApInMwaitLoop Equ 2
+ApInRunLoop Equ 3
+
+LockLocation equ 1000h - 0400h
+StackStart equ LockLocation + 4h
+StackSize equ LockLocation + 8h
+RendezvousProc equ LockLocation + 0Ch
+GdtrProfile equ LockLocation + 10h
+IdtrProfile equ LockLocation + 16h
+BufferStart equ LockLocation + 1Ch
+Cr3Location equ LockLocation + 20h
+InitFlag equ LockLocation + 24h
+WakeUpApManner equ LockLocation + 28h
+BistBuffer equ LockLocation + 2Ch
+PAUSE32 MACRO
+ DB 0F3h
+ DB 090h
+ ENDM
+
+;-------------------------------------------------------------------------------
diff --git a/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/Ia32/InitializeFpu.s b/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/Ia32/InitializeFpu.s
new file mode 100644
index 0000000000..782eb00bb6
--- /dev/null
+++ b/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/Ia32/InitializeFpu.s
@@ -0,0 +1,72 @@
+## @file
+# Copyright (c) 2009 - 2015, 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
+#
+##
+
+#
+# Float control word initial value:
+# all exceptions masked, double-precision, round-to-nearest
+#
+ASM_PFX(mFpuControlWord): .word 0x027F
+#
+# Multimedia-extensions control word:
+# all exceptions masked, round-to-nearest, flush to zero for masked underflow
+#
+ASM_PFX(mMmxControlWord): .long 0x01F80
+
+#
+# Initializes floating point units for requirement of UEFI specification.
+#
+# This function initializes floating-point control word to 0x027F (all exceptions
+# masked,double-precision, round-to-nearest) and multimedia-extensions control word
+# (if supported) to 0x1F80 (all exceptions masked, round-to-nearest, flush to zero
+# for masked underflow).
+#
+ASM_GLOBAL ASM_PFX(InitializeFloatingPointUnits)
+ASM_PFX(InitializeFloatingPointUnits):
+
+ pushl %ebx
+
+ #
+ # Initialize floating point units
+ #
+ finit
+ fldcw ASM_PFX(mFpuControlWord)
+
+ #
+ # Use CpuId instructuion (CPUID.01H:EDX.SSE[bit 25] = 1) to test
+ # whether the processor supports SSE instruction.
+ #
+ movl $1, %eax
+ cpuid
+ btl $25, %edx
+ jnc Done
+
+ #
+ # Set OSFXSR bit 9 in CR4
+ #
+ movl %cr4, %eax
+ or $0x200, %eax
+ movl %eax, %cr4
+
+ #
+ # The processor should support SSE instruction and we can use
+ # ldmxcsr instruction
+ #
+ ldmxcsr ASM_PFX(mMmxControlWord)
+
+Done:
+ popl %ebx
+
+ ret
+
+#END
+
diff --git a/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/Ia32/MPFuncs32.asm b/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/Ia32/MPFuncs32.asm
new file mode 100644
index 0000000000..1350addb7d
--- /dev/null
+++ b/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/Ia32/MPFuncs32.asm
@@ -0,0 +1,426 @@
+;; @file
+; This is the assembly code for MP (Multiple-processor) support
+;
+; Copyright (c) 1999 - 2015, 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.
+;
+;;
+
+.686p
+.model flat
+.code
+
+include Htequ.inc
+;-------------------------------------------------------------------------------------
+FJMP32 MACRO Selector, Offset
+ DB 066h
+ DB 067h
+ DB 0EAh ; far jump
+ DD Offset ; 32-bit offset
+ DW Selector ; 16-bit selector
+ ENDM
+FCALL32 MACRO Selector, Offset
+ DB 09Ah
+ DD Offset ; 32-bit offset
+ DW Selector ; 16-bit selector
+ ENDM
+;-------------------------------------------------------------------------------------
+;RendezvousFunnelProc 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.
+;-------------------------------------------------------------------------------------
+;RendezvousFunnelProc (&WakeUpBuffer,MemAddress);
+
+RendezvousFunnelProc PROC near C PUBLIC
+RendezvousFunnelProcStart::
+
+
+; At this point CS = 0x(vv00) and ip= 0x0.
+
+ db 66h, 08bh, 0e8h ; mov ebp, eax
+
+ 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
+
+; Get APIC ID
+;
+ db 66h, 0B8h
+ dd 00000001h ; mov eax, 1
+ db 0Fh, 0A2h ; cpuid
+ db 66h, 0C1h, 0EBh, 18h ; shr ebx, 24
+ db 66h, 81h, 0E3h
+ dd 000000FFh ; and ebx, 0ffh ; EBX is keeping APIC ID
+
+; If it is the first time AP wakes up, just record AP's BIST
+; Otherwise, switch to flat mode
+
+ db 0BEh, 24h, 0Ch ; mov si, InitFlag
+ db 66h, 83h, 3Ch, 01h ; cmp dword ptr [si], 1
+ db 75h, 18h ; jnz flat32Start
+
+; Record BIST information
+;
+ db 0B0h, 08h ; mov al, 8
+ db 0F6h, 0E3h ; mul bl
+
+ db 0BEh, 2Ch, 0Ch ; mov si, BistBuffer
+ db 03h, 0F0h ; add si, ax
+
+ db 66h, 0C7h, 04h
+ dd 00000001h ; mov dword ptr [si], 1 ; Set Valid Flag
+ db 66h, 89h, 6Ch, 04h ; mov dword ptr [si + 4], ebp ; Store BIST value
+
+ cli
+ hlt
+ jmp $-2
+
+; Switch to flat mode.
+
+flat32Start::
+
+ db 0BEh, 1Ch, 0Ch ; mov si, BufferStart
+ db 66h, 8Bh, 0Ch ; mov ecx,dword ptr [si] ; ECX is keeping the start address of wakeup buffer
+
+ db 0FAh ; cli
+ db 0BEh, 10h, 0Ch ; mov si, GdtrProfile
+ db 66h ; db 66h
+ db 2Eh,0Fh, 01h, 14h ; lgdt fword ptr cs:[si]
+
+ db 0BEh, 16h, 0Ch ; 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, 01h ; or eax, 000000001h ; Set PE bit (bit #0)
+ db 0Fh, 22h, 0C0h ; mov cr0, eax
+
+
+;step-4:
+
+FLAT32_JUMP::
+ FJMP32 010h,0h ; Far jmp using code segment descriptor
+
+PMODE_ENTRY:: ; protected mode entry point
+
+ mov ax, 8h
+ mov ds, ax
+ mov es, ax
+ mov fs, ax
+ mov gs, ax
+ mov ss, ax ; Flat mode setup.
+
+ mov esi, ecx
+
+ mov edi, esi
+ add edi, InitFlag
+ cmp dword ptr [edi], 2 ; Check whether in S3 boot path
+ jz ProgramDynamicStack
+
+ProgramStaticStack::
+
+ xor ecx, ecx
+ mov edi, esi
+ add edi, BistBuffer
+ mov ecx, dword ptr [edi + 8 * ebx] ; EBX = CpuNumber
+
+ mov edi, esi
+ add edi, StackSize
+ mov eax, dword ptr [edi]
+ inc ecx
+ mul ecx ; EAX = StackSize * (CpuNumber + 1)
+
+ mov edi, esi
+ add edi, StackStart
+ mov edx, dword ptr [edi]
+ add eax, edx ; EAX = StackStart + StackSize * (CpuNumber + 1)
+
+ mov esp, eax
+ sub esp, MonitorFilterSize ; Reserved Monitor data space
+ or ebx, StartupApSignal ; ebx = #Cpu run signature
+ jmp ProgramLocalApic
+
+ProgramDynamicStack::
+
+ mov edi, esi
+ add edi, LockLocation
+ mov al, NotVacantFlag
+TestLock::
+ xchg byte ptr [edi], al
+ cmp al, NotVacantFlag
+ jz TestLock
+
+ mov edi, esi
+ add edi, StackSize
+ mov eax, dword ptr [edi]
+ mov edi, esi
+ add edi, StackStart
+ add eax, dword ptr [edi]
+ mov esp, eax
+ mov dword ptr [edi], eax
+
+Releaselock::
+ mov al, VacantFlag
+ mov edi, esi
+ add edi, LockLocation
+ xchg byte ptr [edi], al
+
+ProgramLocalApic::
+
+ mov edi, 0FEE000F0h
+ mov eax, dword ptr [edi]
+ and eax, 0FFFFFD0Fh
+ or eax, 10Fh
+ mov dword ptr [edi], eax
+
+ mov edi, 0FEE00350h
+ mov eax, dword ptr [edi]
+ and eax, 0FFFE00FFh
+ or eax, 700h
+ mov dword ptr [edi], eax
+
+ mov edi, 0FEE00360h
+ mov eax, dword ptr [edi]
+ and eax, 0FFFE00FFh
+ or eax, 10400h
+ mov dword ptr [edi], eax
+
+EnableXmm::
+ mov eax, 1
+ cpuid
+ bt edx,1Ah
+ jnc @F
+ ;
+ ; Enable XMM
+ ;
+ mov eax,cr0
+ or eax, 2
+ mov cr0, eax
+ mov eax, cr4
+ or eax, 600h
+ mov cr4, eax
+
+@@:
+ ;
+ ; Call C Function
+ ;
+ mov edi, esi
+ add edi, RendezvousProc
+ add esi, WakeUpApManner ; esi = WakeUpApManner Address Location
+
+WakeUpThisAp::
+
+ mov eax, dword ptr [edi]
+
+ test eax, eax
+ jz CheckWakeUpCounterInit
+
+ push ebx
+ push ebx
+ push esi
+ push edi
+
+ sub esp, 20h
+ call eax ; Call C function
+ add esp, 20h
+
+ pop edi
+ pop esi
+ pop ebx
+ pop ebx
+
+CheckWakeUpCounterInit::
+ cmp dword ptr [esi], ApCounterInit
+ jnz CheckWakeUpManner
+
+;
+; Initialize MONITOR_MWAIT_DATA data structure per thread
+;
+ xor ecx, ecx
+ mov dword ptr [esp + 0], ecx ; BreakToRunApSignal
+ mov dword ptr [esp + 4], ecx ; HltLoopBreakCounter
+ mov dword ptr [esp + 8], ecx ; MwaitLoopBreakCounter
+ mov dword ptr [esp + 12], ecx ; RunLoopBreakCounter
+ mov dword ptr [esp + 16], ecx ; WakeUpApVectorChangeFlag
+ mov dword ptr [esp + 20], ecx ; MwaitTargetCstate
+
+CheckWakeUpManner::
+
+ cmp dword ptr [esi], ApInHltLoop
+ jz HltApLoop
+
+ cmp dword ptr [esi], ApInMwaitLoop
+ jnz CheckRunSignal
+
+ApMwaitLoop::
+
+ cli
+ mov eax, esp ; Set Monitor Address
+ xor ecx, ecx
+ xor edx, edx
+ DB 0fh, 1, 0c8h ; MONITOR
+ mov eax, dword ptr [esp + 20] ; Mwait Target C-State per rax[7:4]
+ DB 0fh, 1, 0c9h ; MWAIT
+
+CheckRunSignal::
+
+ cmp dword ptr [esp], ebx ; Check if run signal correct?
+ jnz CheckWakeUpManner ; Unknown break, go checking run manner
+
+ jmp WakeUpThisAp ; Jmp to execute AP task
+
+HltApLoop::
+
+ cli
+ hlt
+ jmp HltApLoop
+
+RendezvousFunnelProc ENDP
+RendezvousFunnelProcEnd::
+;-------------------------------------------------------------------------------------
+; AsmGetAddressMap (&AddressMap);
+;-------------------------------------------------------------------------------------
+AsmGetAddressMap PROC near C PUBLIC
+
+ pushad
+ mov ebp,esp
+
+ mov ebx, dword ptr [ebp+24h]
+ mov dword ptr [ebx], RendezvousFunnelProcStart
+ mov dword ptr [ebx+4h], PMODE_ENTRY - RendezvousFunnelProcStart
+ mov dword ptr [ebx+8h], FLAT32_JUMP - RendezvousFunnelProcStart
+ mov dword ptr [ebx+0ch], RendezvousFunnelProcEnd - RendezvousFunnelProcStart
+
+ popad
+ ret
+AsmGetAddressMap ENDP
+
+;-------------------------------------------------------------------------------------
+;AsmExchangeRole procedure follows. This procedure executed by current BSP, that is
+;about to become an AP. It switches it'stack with the current AP.
+;AsmExchangeRole (IN CPU_EXCHANGE_INFO *MyInfo, IN CPU_EXCHANGE_INFO *OthersInfo);
+;-------------------------------------------------------------------------------------
+CPU_SWITCH_STATE_IDLE equ 0
+CPU_SWITCH_STATE_STORED equ 1
+CPU_SWITCH_STATE_LOADED equ 2
+
+AsmExchangeRole PROC near C PUBLIC
+ ; DO NOT call other functions in this function, since 2 CPU may use 1 stack
+ ; at the same time. If 1 CPU try to call a functiosn, stack will be corrupted.
+ pushad
+ mov ebp,esp
+
+ ; esi contains MyInfo pointer
+ mov esi, dword ptr [ebp+24h]
+
+ ; edi contains OthersInfo pointer
+ mov edi, dword ptr [ebp+28h]
+
+ ;Store EFLAGS, GDTR and IDTR regiter to stack
+ pushfd
+ sgdt fword ptr [esi+8]
+ sidt fword ptr [esi+14]
+
+ ; Store the its StackPointer
+ mov dword ptr [esi+4],esp
+
+ ; update its switch state to STORED
+ mov al, NotVacantFlag
+TryLock1:
+ db 0f0h ; opcode for lock instruction
+ xchg al, byte ptr [esi]
+ cmp al, VacantFlag
+ jz LockObtained1
+ PAUSE32
+ jmp TryLock1
+
+LockObtained1:
+ mov byte ptr [esi+1], CPU_SWITCH_STATE_STORED
+ db 0f0h ; opcode for lock instruction
+ xchg al, byte ptr [esi]
+
+WaitForOtherStored::
+ ; wait until the other CPU finish storing its state
+ mov al, NotVacantFlag
+TryLock2:
+ db 0f0h ; opcode for lock instruction
+ xchg al, byte ptr [edi]
+ cmp al, VacantFlag
+ jz LockObtained2
+ PAUSE32
+ jmp TryLock2
+
+LockObtained2:
+ mov bl, byte ptr [edi+1]
+ db 0f0h ; opcode for lock instruction
+ xchg al, byte ptr [edi]
+ cmp bl, CPU_SWITCH_STATE_STORED
+ jb WaitForOtherStored
+
+ ; Since another CPU already stored its state, load them
+ ; load GDTR value
+ lgdt fword ptr [edi+8]
+
+ ; load IDTR value
+ lidt fword ptr [edi+14]
+
+ ; load its future StackPointer
+ mov esp, dword ptr [edi+4]
+
+ ; update its switch state to LOADED
+ mov al, NotVacantFlag
+TryLock3:
+ db 0f0h ; opcode for lock instruction
+ xchg al, byte ptr [esi]
+ cmp al, VacantFlag
+ jz LockObtained3
+ PAUSE32
+ jmp TryLock3
+
+LockObtained3:
+ mov byte ptr [esi+1], CPU_SWITCH_STATE_LOADED
+ db 0f0h ; opcode for lock instruction
+ xchg al, byte ptr [esi]
+
+WaitForOtherLoaded::
+ ; wait until the other CPU finish loading new state,
+ ; otherwise the data in stack may corrupt
+ mov al, NotVacantFlag
+TryLock4:
+ db 0f0h ; opcode for lock instruction
+ xchg al, byte ptr [edi]
+ cmp al, VacantFlag
+ jz LockObtained4
+ PAUSE32
+ jmp TryLock4
+
+LockObtained4:
+ mov bl, byte ptr [edi+1]
+ db 0f0h ; opcode for lock instruction
+ xchg al, byte ptr [edi]
+ cmp bl, CPU_SWITCH_STATE_LOADED
+ jb WaitForOtherLoaded
+
+ ; since the other CPU already get the data it want, leave this procedure
+ popfd
+
+ popad
+ ret
+AsmExchangeRole ENDP
+END
diff --git a/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/Ia32/MPFuncs32.s b/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/Ia32/MPFuncs32.s
new file mode 100644
index 0000000000..fd44beae0b
--- /dev/null
+++ b/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/Ia32/MPFuncs32.s
@@ -0,0 +1,444 @@
+## @file
+# This is the assembly code for MP (Multiple-processor) support.
+#
+# Copyright (c) 1999 - 2015, 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 Htequ.inc
+
+.equ VacantFlag , 0x00
+.equ NotVacantFlag , 0xff
+.equ StartupApSignal , 0x6E750000
+.equ MonitorFilterSize, 0x10
+.equ ApCounterInit , 0
+.equ ApInHltLoop , 1
+.equ ApInMwaitLoop , 2
+.equ ApInRunLoop , 3
+
+.equ LockLocation , 0x1000 - 0x0400
+.equ StackStart , LockLocation + 0x4
+.equ StackSize , LockLocation + 0x8
+.equ RendezvousProc , LockLocation + 0x0C
+.equ GdtrProfile , LockLocation + 0x10
+.equ IdtrProfile , LockLocation + 0x16
+.equ BufferStart , LockLocation + 0x1C
+.equ Cr3Location , LockLocation + 0x20
+.equ InitFlag , LockLocation + 0x24
+.equ WakeUpApManner , LockLocation + 0x28
+.equ BistBuffer , LockLocation + 0x2C
+
+#-------------------------------------------------------------------------------------
+
+.macro PAUSE32
+ .byte 0xF3
+ .byte 0x90
+.endm
+
+.macro FJMP32 Selector, Offset
+ .byte 0x066
+ .byte 0x067
+ .byte 0x0EA # far jump
+ .long \Offset # 32-bit offset
+ .word \Selector # 16-bit selector
+.endm
+
+.macro FCALL32 Selector, Offset
+ .byte 0x09A
+ .long \Offset # 32-bit offset
+ .word \Selector # 16-bit selector
+.endm
+
+#-------------------------------------------------------------------------------------
+#RendezvousFunnelProc 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.
+#-------------------------------------------------------------------------------------
+#RendezvousFunnelProc (&WakeUpBuffer,MemAddress)
+
+ASM_GLOBAL ASM_PFX(RendezvousFunnelProc)
+ASM_PFX(RendezvousFunnelProc):
+RendezvousFunnelProcStart:
+
+# At this point CS = 0x(vv00) and ip= 0x0.
+
+ .byte 0x66,0x8b,0xe8 # mov ebp, eax
+
+ .byte 0x8c,0xc8 # mov ax, cs
+ .byte 0x8e,0xd8 # mov ds, ax
+ .byte 0x8e,0xc0 # mov es, ax
+ .byte 0x8e,0xd0 # mov ss, ax
+ .byte 0x33,0xc0 # xor ax, ax
+ .byte 0x8e,0xe0 # mov fs, ax
+ .byte 0x8e,0xe8 # mov gs, ax
+
+# Get APIC ID
+#
+ .byte 0x66, 0xB8
+ .long 0x00000001 # mov %eax, 1
+ .byte 0x0F, 0xA2 # cpuid
+ .byte 0x66, 0xC1, 0xEB, 0x18 # shr %ebx, 24
+ .byte 0x66, 0x81, 0xE3
+ .long 0x000000FF # and %ebx, 0ffh # EBX is keeping APIC ID
+
+# If it is the first time AP wakes up, just record AP's BIST
+# Otherwise, switch to flat mode
+
+ .byte 0xBE, 0x24, 0x0C # mov si, InitFlag
+ .byte 0x66, 0x83, 0x3C, 0x01 # cmp dword ptr [si], 1
+ .byte 0x75, 0x18 # jnz flat32Start
+
+# Record BIST information
+#
+ .byte 0xB0, 0x08 # mov al, 8
+ .byte 0xF6, 0xE3 # mul bl
+
+ .byte 0xBE, 0x2C, 0x0C # mov si, BistBuffer
+ .byte 0x03, 0xF0 # add si, ax
+
+ .byte 0x66, 0xC7, 0x04
+ .byte 0x00000001 # mov dword ptr [si], 1 # Set Valid Flag
+ .byte 0x66, 0x89, 0x6C, 0x04 # mov dword ptr [si + 4], ebp # Store BIST value
+
+ cli
+ hlt
+ jmp .-2
+
+# Switch to flat mode.
+
+flat32Start:
+
+ .byte 0xBE, 0x1C, 0x0C # mov si, BufferStart
+ .byte 0x66, 0x8B, 0x0C # mov ecx,dword ptr [si] # ECX is keeping the start address of wakeup buffer
+
+ .byte 0xFA # cli
+ .byte 0xBE, 0x10, 0x0C # mov si, GdtrProfile
+ .byte 0x66 # db 66h
+ .byte 0x2E, 0x0F, 0x01, 0x14 # lgdt fword ptr cs:[si]
+
+ .byte 0xBE, 0x16, 0x0C # mov si, IdtrProfile
+ .byte 0x66 # db 66h
+ .byte 0x2E, 0x0F, 0x01, 0x1C # lidt fword ptr cs:[si]
+
+
+ .byte 0x33, 0xC0 # xor ax, ax
+ .byte 0x8E, 0xD8 # mov ds, ax
+ .byte 0x0F, 0x20, 0xC0 # mov eax, cr0 # Get control register 0
+ .byte 0x66, 0x83, 0xC8, 0x01 # or eax, 000000001h # Set PE bit (bit #0)
+ .byte 0x0F, 0x22, 0xC0 # mov cr0, eax
+
+
+#step-4:
+
+FLAT32_JUMP:
+ FJMP32 0x010, 0x0 # Far jmp using code segment descriptor
+
+PMODE_ENTRY: # protected mode entry point
+
+ movw $0x8,%ax
+ movw %ax,%ds
+ movw %ax,%es
+ movw %ax,%fs
+ movw %ax,%gs
+ movw %ax,%ss # Flat mode setup.
+
+ movl %ecx,%esi
+
+ movl %esi,%edi
+ addl $InitFlag, %edi
+ cmpl $2, (%edi) # Check whether in S3 boot path
+ jz ProgramDynamicStack
+
+ProgramStaticStack:
+
+ xorl %ecx, %ecx
+ movl %esi, %edi
+ addl $BistBuffer, %edi
+ movl (%edi, %ebx, 8), %ecx # EBX = CpuNumber
+
+ movl %esi, %edi
+ addl $StackSize, %edi
+ movl (%edi), %eax
+ incl %ecx
+ mull %ecx # EAX = StackSize * (CpuNumber + 1)
+
+ movl %esi, %edi
+ addl $StackStart, %edi
+ movl (%edi), %edx
+ addl %edx, %eax # EAX = StackStart + StackSize * (CpuNumber + 1)
+
+ movl %eax, %esp
+ subl $MonitorFilterSize, %esp # Reserved Monitor data space
+ orl $StartupApSignal, %ebx # EBX = #Cpu run signature
+ jmp ProgramLocalApic
+
+ProgramDynamicStack:
+
+ movl %esi, %edi
+ addl $LockLocation, %edi
+ movb $NotVacantFlag, %al
+TestLock:
+ xchgb %al, (%edi)
+ cmpb $NotVacantFlag, %al
+ jz TestLock
+
+ movl %esi, %edi
+ addl $StackSize, %edi
+ movl (%edi), %eax
+ movl %esi, %edi
+ addl $StackStart, %edi
+ addl (%edi), %eax
+ movl %eax, %esp
+ movl %eax, (%edi)
+
+Releaselock:
+ movb $VacantFlag, %al
+ movl %esi, %edi
+ addl $LockLocation, %edi
+ xchgb %al, (%edi)
+
+ProgramLocalApic:
+
+ movl $0x0FEE000F0, %edi
+ movl (%edi), %eax
+ andl $0x0FFFFFD0F, %eax
+ orl $0x10F, %eax
+ movl %eax, (%edi)
+
+ movl $0x0FEE00350, %edi
+ movl (%edi), %eax
+ andl $0x0FFFE00FF, %eax
+ orl $0x700, %eax
+ movl %eax, (%edi)
+
+ movl $0x0FEE00360, %edi
+ movl (%edi), %eax
+ andl $0x0FFFE00FF, %eax
+ orl $0x10400, %eax
+ movl %eax, (%edi)
+EnableXmm:
+ movl $1, %eax
+ cpuid
+ btl $0x1A, %edx
+ jnc L1
+ #
+ # Enable XMM
+ #
+ movl %cr0, %eax
+ orl $2, %eax
+ movl %eax, %cr0
+ movl %cr4, %eax
+ orl $0x600, %eax
+ movl %eax, %cr4
+
+L1:
+ #
+ # Call C Function
+ #
+ movl %esi, %edi
+ addl $RendezvousProc, %edi
+ addl $WakeUpApManner, %esi # esi = WakeUpApManner Address Location
+
+WakeUpThisAp:
+
+ movl (%edi), %eax
+
+ testl %eax, %eax
+ jz CheckWakeUpCounterInit
+
+ push %ebx
+ push %ebx
+ push %esi
+ push %edi
+
+ subl $0x20, %esp
+ call *%eax # Call C function
+ addl $0x20, %esp
+
+ pop %edi
+ pop %esi
+ pop %ebx
+ pop %ebx
+
+CheckWakeUpCounterInit:
+ cmpl $ApCounterInit, (%esi)
+ jnz CheckWakeUpManner
+
+#
+# Initi%alize MONITOR_MWAIT_DATA data structure per thread
+#
+ xorl %ecx, %ecx
+ movl %ecx, 0(%esp) # BreakToRunApSignal
+ movl %ecx, 4(%esp) # HltLoopBreakCounter
+ movl %ecx, 8(%esp) # MwaitLoopBreakCounter
+ movl %ecx, 12(%esp) # RunLoopBreakCounter
+ movl %ecx, 16(%esp) # WakeUpApVectorChangeFlag
+ movl %ecx, 20(%esp) # MwaitTargetCstate
+
+CheckWakeUpManner:
+
+ cmpl $ApInHltLoop, (%esi)
+ jz HltApLoop
+
+ cmpl $ApInMwaitLoop, (%esi)
+ jnz CheckRunSignal
+
+ApMwaitLoop:
+
+ cli
+ movl %esp, %eax # Set Monitor Address
+ xorl %ecx, %ecx
+ xorl %edx, %edx
+ .byte 0x0f, 0x1, 0xc8 # MONITOR
+ movl 20(%esp), %eax # Mwait Target C-State per rax[7:4]
+ .byte 0x0f, 0x1, 0xc9 # MWAIT
+
+CheckRunSignal:
+
+ cmpl %ebx, (%esp) # Check if run sign%al correct?
+ jnz CheckWakeUpManner # Unknown break, go checking run manner
+
+ jmp WakeUpThisAp # Jmp to execute AP task
+
+HltApLoop:
+
+ cli
+ hlt
+ jmp HltApLoop
+
+#RendezvousFunnelProc ENDP
+RendezvousFunnelProcEnd:
+
+#-------------------------------------------------------------------------------------
+# AsmGetAddressMap (&AddressMap)
+#-------------------------------------------------------------------------------------
+ASM_GLOBAL ASM_PFX(AsmGetAddressMap)
+ASM_PFX(AsmGetAddressMap):
+ pushal
+ movl %esp, %ebp
+
+ movl 0x24(%ebp), %ebx
+ movl $RendezvousFunnelProcStart, (%ebx)
+ movl $(PMODE_ENTRY - RendezvousFunnelProcStart), 0x4(%ebx)
+ movl $(FLAT32_JUMP - RendezvousFunnelProcStart), 0x8(%ebx)
+ movl $(RendezvousFunnelProcEnd - RendezvousFunnelProcStart), 0xc(%ebx)
+
+ popal
+ ret
+#AsmGetAddressMap ENDP
+
+#-------------------------------------------------------------------------------------
+#AsmExchangeRole procedure follows. This procedure executed by current BSP, that is
+#about to become an AP. It switches it'stack with the current AP.
+#AsmExchangeRole (IN CPU_EXCHANGE_INFO *MyInfo, IN CPU_EXCHANGE_INFO *OthersInfo)#
+#-------------------------------------------------------------------------------------
+.equ CPU_SWITCH_STATE_IDLE, 0
+.equ CPU_SWITCH_STATE_STORED, 1
+.equ CPU_SWITCH_STATE_LOADED, 2
+
+ASM_GLOBAL ASM_PFX(AsmExchangeRole)
+ASM_PFX(AsmExchangeRole):
+ # DO NOT call other functions in this function, since 2 CPU may use 1 stack
+ # at the same time. If 1 CPU try to call a functiosn, stack will be corrupted.
+ pushal
+ movl %esp, %ebp
+
+ # %esi contains MyInfo pointer
+ movl 0x24(%ebp), %esi
+
+ # %edi contains OthersInfo pointer
+ movl 0x28(%ebp), %edi
+
+ #Store EFLAGS, GDTR and IDTR regiter to stack
+ pushfl
+ sgdt 8(%esi)
+ sidt 14(%esi)
+
+ # Store the its StackPointer
+ movl %esp, 4(%esi)
+
+ # update its switch state to STORED
+ movb $NotVacantFlag, %al
+TryLock1:
+ lock xchgb (%esi), %al
+ cmpb $VacantFlag, %al
+ jz LockObtained1
+ PAUSE32
+ jmp TryLock1
+
+LockObtained1:
+ movb $CPU_SWITCH_STATE_STORED, 1(%esi)
+ lock xchgb (%esi), %al
+WaitForOtherStored:
+ # wait until the other CPU finish storing its state
+ movb $NotVacantFlag, %al
+TryLock2:
+ lock xchgb (%edi), %al
+ cmpb $VacantFlag, %al
+ jz LockObtained2
+ PAUSE32
+ jmp TryLock2
+
+LockObtained2:
+ movb 1(%edi), %bl
+ lock xchgb (%edi), %al
+ cmpb $CPU_SWITCH_STATE_STORED, %bl
+ jb WaitForOtherStored
+
+ # Since another CPU already stored its state, load them
+ # load GDTR value
+ lgdt 8(%edi)
+
+ # load IDTR value
+ lidt 14(%edi)
+
+ # load its future StackPointer
+ movl 4(%edi), %esp
+
+ # update its switch state to LOADED
+ movb $NotVacantFlag, %al
+TryLock3:
+ lock xchgb (%esi), %al
+ cmpb $VacantFlag, %al
+ jz LockObtained3
+ PAUSE32
+ jmp TryLock3
+
+LockObtained3:
+ movb $CPU_SWITCH_STATE_LOADED, 1(%esi)
+ lock xchgb (%esi), %al
+
+WaitForOtherLoaded:
+ # wait until the other CPU finish loading new state,
+ # otherwise the data in stack may corrupt
+ movb $NotVacantFlag, %al
+TryLock4:
+ lock xchgb (%edi), %al
+ cmpb $VacantFlag, %al
+ jz LockObtained4
+ PAUSE32
+ jmp TryLock4
+
+LockObtained4:
+ movb 1(%edi), %bl
+ lock xchgb (%edi), %al
+ cmpb $CPU_SWITCH_STATE_LOADED, %bl
+ jb WaitForOtherLoaded
+
+ # since the other CPU already get the data it want, leave this procedure
+ popfl
+
+ popal
+ ret
+#AsmExchangeRole ENDP
+
diff --git a/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/Ia32/MemoryOperation.c b/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/Ia32/MemoryOperation.c
new file mode 100644
index 0000000000..ab196d140b
--- /dev/null
+++ b/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/Ia32/MemoryOperation.c
@@ -0,0 +1,380 @@
+/** @file
+ Memory Operation Functions for IA32 Architecture.
+
+ Copyright (c) 2014 - 2015, 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 "CpuDxe.h"
+#include "MpCommon.h"
+#include "PlatformMpService.h"
+
+VOID
+InitializeIdt (
+ IN EFI_CPU_INTERRUPT_HANDLER *TableStart,
+ IN UINTN *IdtTablePtr,
+ IN UINT16 IdtTableLimit
+ );
+
+extern EFI_CPU_INTERRUPT_HANDLER mExternalVectorTable[];
+extern EFI_PHYSICAL_ADDRESS mBackupBuffer;
+
+UINT64 mValidMtrrAddressMask = EFI_CACHE_VALID_ADDRESS;
+UINT64 mValidMtrrBitsMask = EFI_MSR_VALID_MASK;
+
+/**
+ Slick around interrupt routines.
+
+ @retval EFI_SUCCESS - If interrupt settings are initialized successfully
+
+**/
+EFI_STATUS
+InitializeSlick (
+ VOID
+ )
+{
+ INTERRUPT_GATE_DESCRIPTOR *IdtTable;
+ INTERRUPT_HANDLER_TEMPLATE_MAP TemplateMap;
+ UINT16 CodeSegment;
+ INTERRUPT_GATE_DESCRIPTOR *IdtEntry;
+ UINT8 *InterruptHandler;
+ UINT8 *CurrentHandler;
+ UINTN Index;
+
+ IdtTable = AllocatePool (sizeof (INTERRUPT_GATE_DESCRIPTOR) * INTERRUPT_VECTOR_NUMBER);
+ ASSERT(IdtTable != NULL);
+ IdtEntry = IdtTable;
+
+ GetTemplateAddressMap (&TemplateMap);
+ InterruptHandler = AllocatePool (TemplateMap.Size * INTERRUPT_VECTOR_NUMBER);
+ ASSERT(InterruptHandler != NULL);
+ CurrentHandler = InterruptHandler;
+
+ CodeSegment = GetCodeSegment ();
+
+ for (Index = 0; Index < INTERRUPT_VECTOR_NUMBER; Index++) {
+ CopyMem (CurrentHandler, TemplateMap.Start, TemplateMap.Size);
+ *(UINT32 *) (CurrentHandler + TemplateMap.FixOffset) = Index;
+
+ IdtEntry[Index].OffsetLow = (UINT16) (UINTN) CurrentHandler;
+ IdtEntry[Index].SegmentSelector = CodeSegment;
+ IdtEntry[Index].Attributes = INTERRUPT_GATE_ATTRIBUTE;
+ //
+ // 8e00;
+ //
+ IdtEntry[Index].OffsetHigh = (UINT16) ((UINTN) CurrentHandler >> 16);
+
+ CurrentHandler += TemplateMap.Size;
+ }
+
+ InitializeIdt (
+ &(mExternalVectorTable[0]),
+ (UINTN *) IdtTable,
+ sizeof (INTERRUPT_GATE_DESCRIPTOR) * INTERRUPT_VECTOR_NUMBER
+ );
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Prepare memory for essential system tables.
+
+ @retval EFI_SUCCESS Memory successfully prepared.
+ @retval Other Error occurred while initializating memory.
+
+**/
+EFI_STATUS
+PrepareMemory (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+
+ ZeroMem (mExternalVectorTable, 0x100 * 4);
+
+ //
+ // Initialize the Interrupt Descriptor Table
+ //
+ Status = InitializeSlick ();
+
+ return Status;
+}
+
+/**
+ Prepare Wakeup Buffer and stack for APs.
+
+ @param[out] WakeUpBuffer - Pointer to the address of wakeup buffer for output.
+ @param[out] StackAddressStart - Pointer to the stack address of APs for output.
+ @param[in] MaximumCPUsForThisSystem - Maximum CPUs in this system.
+
+ @retval EFI_SUCCESS - Memory successfully prepared for APs.
+ @retval Other - Error occurred while allocating memory.
+
+**/
+EFI_STATUS
+PrepareMemoryForAPs (
+ OUT EFI_PHYSICAL_ADDRESS *WakeUpBuffer,
+ OUT VOID **StackAddressStart,
+ IN UINTN MaximumCPUsForThisSystem
+ )
+{
+ EFI_STATUS Status;
+ MP_ASSEMBLY_ADDRESS_MAP AddressMap;
+
+ //
+ // Release All APs with a lock and wait for them to retire to rendezvous procedure.
+ // We need a 64 aligned 4K aligned area for IA-32 to use broadcast APIs. But we need it only
+ // on a temporary basis.
+ //
+ Status = AllocateWakeUpBuffer (WakeUpBuffer);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Claim memory for AP stack.
+ //
+ Status = gBS->AllocatePool (
+ EfiACPIMemoryNVS,
+ MaximumCPUsForThisSystem * STACK_SIZE_PER_PROC,
+ StackAddressStart
+ );
+ if (EFI_ERROR (Status)) {
+ gBS->FreePages (*WakeUpBuffer, 1);
+ return Status;
+ }
+
+ AsmGetAddressMap (&AddressMap);
+ CopyMem ((VOID *) (UINTN) *WakeUpBuffer, AddressMap.RendezvousFunnelAddress, AddressMap.Size);
+ *(UINT32 *) (UINTN) (*WakeUpBuffer + AddressMap.FlatJumpOffset + 3) = (UINT32) (*WakeUpBuffer + AddressMap.PModeEntryOffset);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Prepare exchange information for APs.
+
+ @param[out] *ExchangeInfo - Pointer to the exchange info buffer for output.
+ @param[in] *StackAddressStart - Start address of APs' stacks.
+ @param[in] *ApFunction - Address of function assigned to AP.
+ @param[in] WakeUpBuffer - Pointer to the address of wakeup buffer.
+
+ @retval EFI_SUCCESS - Exchange Info successfully prepared for APs.
+
+**/
+EFI_STATUS
+PrepareExchangeInfo (
+ OUT MP_CPU_EXCHANGE_INFO *ExchangeInfo,
+ IN VOID *StackAddressStart,
+ IN VOID *ApFunction,
+ IN EFI_PHYSICAL_ADDRESS WakeUpBuffer
+ )
+{
+ gBS->SetMem ((VOID *) ExchangeInfo, EFI_PAGE_SIZE - MP_CPU_EXCHANGE_INFO_OFFSET, 0);
+
+ ExchangeInfo->Lock = VacantFlag;
+ ExchangeInfo->StackStart = StackAddressStart;
+ ExchangeInfo->StackSize = STACK_SIZE_PER_PROC;
+ ExchangeInfo->ApFunction = ApFunction;
+
+ CopyMem (&ExchangeInfo->GdtrProfile, (VOID *) (UINTN) mAcpiCpuData->GdtrProfile, sizeof (IA32_DESCRIPTOR));
+ CopyMem (&ExchangeInfo->IdtrProfile, (VOID *) (UINTN) mAcpiCpuData->IdtrProfile, sizeof (IA32_DESCRIPTOR));
+
+ ExchangeInfo->BufferStart = (UINT32) WakeUpBuffer;
+ ExchangeInfo->InitFlag = 1;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Prepare Wakeup Buffer and stack for APs during S3.
+
+ @param[out] WakeUpBuffer - Pointer to the address of wakeup buffer for output.
+ @param[out] StackAddressStart - Pointer to the stack address of APs for output.
+
+ @retval EFI_SUCCESS - Memory successfully prepared for APs.
+
+**/
+EFI_STATUS
+S3PrepareMemoryForAPs (
+ OUT EFI_PHYSICAL_ADDRESS *WakeUpBuffer,
+ OUT VOID **StackAddressStart
+ )
+{
+ MP_ASSEMBLY_ADDRESS_MAP AddressMap;
+
+ *WakeUpBuffer = mAcpiCpuData->WakeUpBuffer;
+ *StackAddressStart = (VOID *) (UINTN) mAcpiCpuData->StackAddress;
+
+ AsmGetAddressMap (&AddressMap);
+ CopyMem ((VOID *) (UINTN) *WakeUpBuffer, AddressMap.RendezvousFunnelAddress, AddressMap.Size);
+ *(UINT32 *) (UINTN) (*WakeUpBuffer + AddressMap.FlatJumpOffset + 3) = (UINT32) (*WakeUpBuffer + AddressMap.PModeEntryOffset);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Prepare exchange information for APs during S3.
+
+ @param[out] ExchangeInfo - Pointer to the exchange info for output.
+ @param[in] StackAddressStart - Start address of APs' stacks.
+ @param[in] ApFunction - Address of function assigned to AP.
+ @param[in] WakeUpBuffer - Pointer to the address of wakeup buffer.
+
+ @retval EFI_SUCCESS - Exchange Info successfully prepared for APs.
+
+**/
+EFI_STATUS
+S3PrepareExchangeInfo (
+ OUT MP_CPU_EXCHANGE_INFO *ExchangeInfo,
+ IN VOID *StackAddressStart,
+ IN VOID *ApFunction,
+ IN EFI_PHYSICAL_ADDRESS WakeUpBuffer
+ )
+{
+ ExchangeInfo->Lock = VacantFlag;
+ ExchangeInfo->StackStart = (VOID *) (UINTN) StackAddressStart;
+ ExchangeInfo->StackSize = STACK_SIZE_PER_PROC;
+ ExchangeInfo->ApFunction = ApFunction;
+
+ CopyMem (&ExchangeInfo->GdtrProfile, (VOID *) (UINTN) mAcpiCpuData->GdtrProfile, sizeof (IA32_DESCRIPTOR));
+ CopyMem (&ExchangeInfo->IdtrProfile, (VOID *) (UINTN) mAcpiCpuData->IdtrProfile, sizeof (IA32_DESCRIPTOR));
+
+ ExchangeInfo->BufferStart = (UINT32) WakeUpBuffer;
+ ExchangeInfo->InitFlag = 2;
+
+ //
+ // There is no need to initialize CpuNumber and BistBuffer fields in ExchangeInfo here.
+ //
+ return EFI_SUCCESS;
+}
+
+/**
+ Dynamically write the far jump destination in APs' wakeup buffer,
+ in order to refresh APs' CS registers for mode switching.
+
+**/
+VOID
+RedirectFarJump (
+ VOID
+ )
+{
+ MP_ASSEMBLY_ADDRESS_MAP AddressMap;
+
+ AsmGetAddressMap (&AddressMap);
+ *(UINT32 *) (UINTN) (mAcpiCpuData->WakeUpBuffer + AddressMap.FlatJumpOffset + 3) = (UINT32) (mAcpiCpuData->WakeUpBuffer + AddressMap.PModeEntryOffset);
+ return;
+}
+
+/**
+ Set specified IDT entry with given function pointer.
+
+ @param[in] FunctionPointer - Function pointer for IDT entry.
+ @param[out] IdtEntry - The IDT entry to update.
+
+ @retval - The original IDT entry value.
+
+**/
+UINTN
+SetIdtEntry (
+ IN UINTN FunctionPointer,
+ OUT INTERRUPT_GATE_DESCRIPTOR *IdtEntry
+)
+{
+ UINTN OriginalEntry;
+
+ OriginalEntry = ((UINT32) IdtEntry->OffsetHigh << 16) + IdtEntry->OffsetLow;
+
+ IdtEntry->OffsetLow = (UINT16) FunctionPointer;
+ IdtEntry->OffsetHigh = (UINT16) (FunctionPointer >> 16);
+
+ return OriginalEntry;
+}
+
+/**
+ @todo Add function description
+
+ @param[out] *Gdtr - @todo add argument description
+ @param[out] *Idtr - @todo add argument description
+
+ @retval EFI_SUCCESS - @todo Add description for return value
+
+**/
+EFI_STATUS
+PrepareGdtIdtForAP (
+ OUT IA32_DESCRIPTOR *Gdtr,
+ OUT IA32_DESCRIPTOR *Idtr
+ )
+{
+ INTERRUPT_GATE_DESCRIPTOR *IdtForAP;
+ SEGMENT_DESCRIPTOR *GdtForAP;
+ IA32_DESCRIPTOR *IdtrForBSP;
+ IA32_DESCRIPTOR *GdtrForBSP;
+ UINT8 *MceHandler;
+ EFI_STATUS Status;
+
+ AsmGetGdtrIdtr (&GdtrForBSP, &IdtrForBSP);
+
+ //
+ // Allocate reserved memory for IDT
+ //
+ Status = AllocateAlignedReservedMemory (
+ IdtrForBSP->Limit + 1,
+ 8,
+ (VOID **) &IdtForAP
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Allocate reserved memory for GDT
+ //
+ Status = AllocateAlignedReservedMemory (
+ GdtrForBSP->Limit + 1,
+ 8,
+ (VOID **) &GdtForAP
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ Status = gBS->AllocatePool (
+ EfiACPIMemoryNVS,
+ SIZE_OF_MCE_HANDLER,
+ (VOID **) &MceHandler
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // McheHandler content: iret (opcode = 0xcf)
+ //
+ *MceHandler = 0xCF;
+
+ CopyMem (GdtForAP, (VOID *) GdtrForBSP->Base, GdtrForBSP->Limit + 1);
+ CopyMem (IdtForAP, (VOID *) IdtrForBSP->Base, IdtrForBSP->Limit + 1);
+
+ IdtForAP[INTERRUPT_HANDLER_MACHINE_CHECK].OffsetLow = (UINT16) (UINTN) MceHandler;
+ IdtForAP[INTERRUPT_HANDLER_MACHINE_CHECK].OffsetHigh = (UINT16) ((UINTN) MceHandler >> 16);
+
+ //
+ // Create Gdtr, IDTR profile
+ //
+ Gdtr->Base = (UINTN) GdtForAP;
+ Gdtr->Limit = GdtrForBSP->Limit;
+
+ Idtr->Base = (UINTN) IdtForAP;
+ Idtr->Limit = IdtrForBSP->Limit;
+
+ return EFI_SUCCESS;
+}
+
diff --git a/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/Ia32/MpCommon32.asm b/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/Ia32/MpCommon32.asm
new file mode 100644
index 0000000000..25434ad41f
--- /dev/null
+++ b/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/Ia32/MpCommon32.asm
@@ -0,0 +1,103 @@
+;; @file
+; This is the assembly code for MP/HT (Multiple-processor / Hyper-threading) support
+;
+; Copyright (c) 1999 - 2015, 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.
+;
+;;
+
+.686p
+.model flat
+.data
+.stack
+.code
+.MMX
+.XMM
+
+ include Htequ.inc
+PAUSE32 MACRO
+ DB 0F3h
+ DB 090h
+ ENDM
+
+;-------------------------------------------------------------------------------
+; AsmAcquireMPLock (&Lock);
+;-------------------------------------------------------------------------------
+AsmAcquireMPLock PROC near C PUBLIC
+
+ pushad
+ mov ebp,esp
+
+ mov al, NotVacantFlag
+ mov ebx, dword ptr [ebp+24h]
+TryGetLock:
+ db 0f0h ; opcode for lock instruction
+ xchg al, byte ptr [ebx]
+ cmp al, VacantFlag
+ jz LockObtained
+
+ PAUSE32
+ jmp TryGetLock
+
+LockObtained:
+ popad
+ ret
+AsmAcquireMPLock ENDP
+
+;-------------------------------------------------------------------------------
+; AsmReleaseMPLock (&Lock);
+;-------------------------------------------------------------------------------------
+AsmReleaseMPLock PROC near C PUBLIC
+
+ pushad
+ mov ebp,esp
+
+ mov al, VacantFlag
+ mov ebx, dword ptr [ebp+24h]
+ db 0f0h ; opcode for lock instruction
+ xchg al, byte ptr [ebx]
+
+ popad
+ ret
+AsmReleaseMPLock ENDP
+
+;-------------------------------------------------------------------------------
+; AsmGetGdtrIdtr (&Gdt, &Idt);
+;-------------------------------------------------------------------------------------
+AsmGetGdtrIdtr PROC near C PUBLIC
+
+ pushad
+ mov ebp,esp
+
+ sgdt fword ptr GdtDesc
+ lea esi, GdtDesc
+ mov edi, dword ptr [ebp+24h]
+ mov dword ptr [edi], esi
+
+ sidt fword ptr IdtDesc
+ lea esi, IdtDesc
+ mov edi, dword ptr [ebp+28h]
+ mov dword ptr [edi], esi
+
+ popad
+ ret
+AsmGetGdtrIdtr ENDP
+
+GdtDesc:: ; GDT descriptor
+ DW 03fh ; GDT limit
+ DW 0h ; GDT base and limit will be
+ DW 0h ; filled using sgdt
+
+IdtDesc:: ; IDT descriptor
+ DW 0h ; IDT limit
+ DW 0h ; IDT base and limit will be
+ DW 0h ; filled using sidt
+
+END
diff --git a/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/Ia32/MpCommon32.s b/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/Ia32/MpCommon32.s
new file mode 100644
index 0000000000..dc110da96a
--- /dev/null
+++ b/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/Ia32/MpCommon32.s
@@ -0,0 +1,114 @@
+## @file
+# This is the assembly code for MP/HT (Multiple-processor / Hyper-threading) support
+#
+# Copyright (c) 1999 - 2015, 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 Htequ.inc
+
+.equ VacantFlag , 0x00
+.equ NotVacantFlag , 0xff
+.equ StartupApSignal , 0x6E750000
+.equ MonitorFilterSize, 0x10
+.equ ApCounterInit , 0
+.equ ApInHltLoop , 1
+.equ ApInMwaitLoop , 2
+.equ ApInRunLoop , 3
+
+.equ LockLocation , 0x1000 - 0x0400
+.equ StackStart , LockLocation + 0x4
+.equ StackSize , LockLocation + 0x8
+.equ RendezvousProc , LockLocation + 0x0C
+.equ GdtrProfile , LockLocation + 0x10
+.equ IdtrProfile , LockLocation + 0x16
+.equ BufferStart , LockLocation + 0x1C
+.equ Cr3Location , LockLocation + 0x20
+.equ InitFlag , LockLocation + 0x24
+.equ WakeUpApManner , LockLocation + 0x28
+.equ BistBuffer , LockLocation + 0x2C
+
+.macro PAUSE32
+ .byte 0xF3
+ .byte 0x90
+.endm
+
+
+#-------------------------------------------------------------------------------
+# AsmAcquireMPLock (&Lock)
+#-------------------------------------------------------------------------------
+ASM_GLOBAL ASM_PFX(AsmAcquireMPLock)
+ASM_PFX(AsmAcquireMPLock):
+ pushal
+ movl %esp, %ebp
+
+ movb $NotVacantFlag, %al
+ movl 0x24(%ebp), %ebx
+TryGetLock:
+ lock xchgb (%ebx), %al
+ cmpb $VacantFlag, %al
+ jz LockObtained
+
+ PAUSE32
+
+ jmp TryGetLock
+
+LockObtained:
+ popal
+ ret
+#AsmAcquireMPLock ENDP
+
+#-------------------------------------------------------------------------------
+# AsmReleaseMPLock (&Lock)
+#-------------------------------------------------------------------------------
+ASM_GLOBAL ASM_PFX(AsmReleaseMPLock)
+ASM_PFX(AsmReleaseMPLock):
+ pushal
+ movl %esp, %ebp
+
+ movb $VacantFlag, %al
+ movl 0x24(%ebp), %ebx
+ lock xchgb (%ebx), %al
+
+ popal
+ ret
+#AsmReleaseMPLock ENDP
+
+#-------------------------------------------------------------------------------
+# AsmGetGdtrIdtr (&Gdt, &Idt)#
+#-------------------------------------------------------------------------------------
+ASM_GLOBAL ASM_PFX(AsmGetGdtrIdtr)
+ASM_PFX(AsmGetGdtrIdtr):
+ pushal
+ movl %esp, %ebp
+ sgdt GdtDesc
+ leal GdtDesc, %esi
+ movl 0x24(%ebp), %edi
+ movl %esi, (%edi)
+
+ sidt IdtDesc
+ leal IdtDesc, %esi
+ movl 0x28(%ebp), %edi
+ movl %esi, (%edi)
+
+ popal
+ ret
+#AsmGetGdtrIdtr ENDP
+
+GdtDesc: # GDT descriptor
+ .word 0x03f # GDT limit
+ .word 0x0 # GDT base and limit will be
+ .word 0x0 # filled using sgdt
+
+IdtDesc: # IDT descriptor
+ .word 0x0 # IDT limit
+ .word 0x0 # IDT base and limit will be
+ .word 0x0 # filled using sidt
diff --git a/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/Ia32/MpCpu.c b/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/Ia32/MpCpu.c
new file mode 100644
index 0000000000..133e10c57b
--- /dev/null
+++ b/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/Ia32/MpCpu.c
@@ -0,0 +1,90 @@
+/** @file
+ MP Support driver.
+
+ Copyright (c) 1999 - 2015, 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 "CpuDxe.h"
+#include "MpCommon.h"
+#include "PlatformMpService.h"
+
+extern EFI_CPU_MICROCODE_HEADER **mMicrocodePointerBuffer;
+
+ACPI_CPU_DATA_COMPATIBILITY *mAcpiCpuData;
+MP_SYSTEM_DATA *mMPSystemData;
+
+EFI_DEVICE_PATH_PROTOCOL *
+AppendDevicePath (
+ IN EFI_DEVICE_PATH_PROTOCOL *Src1,
+ IN EFI_DEVICE_PATH_PROTOCOL *Src2
+ );
+
+UINTN
+DevicePathSize (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ );
+
+/**
+ Initializes MP support in the system.
+
+ @param[in] ImageHandle Image handle of the loaded driver
+ @param[in] *SystemTable Pointer to the System Table
+
+ @retval EFI_SUCCESS Multiple processors are initialized successfully.
+ @retval EFI_NOT_FOUND The ACPI variable is not found in S3 boot path.
+ @retval EFI_OUT_OF_RESOURCES No enough resoruces (such as out of memory).
+
+**/
+EFI_STATUS
+InitializeMpSupport (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ MP_CPU_RESERVED_DATA *MpCpuReservedData;
+
+ MpCpuReservedData = NULL;
+
+ if (ImageHandle != NULL) {
+
+ Status = AllocateReservedMemoryBelow4G (
+ sizeof (MP_CPU_RESERVED_DATA),
+ (VOID **) &MpCpuReservedData
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ ZeroMem (MpCpuReservedData, sizeof (MP_CPU_RESERVED_DATA));
+
+ mMPSystemData = &(MpCpuReservedData->MPSystemData);
+ mAcpiCpuData = &(MpCpuReservedData->AcpiCpuData);
+
+ CopyMem (
+ MpCpuReservedData->MicrocodePointerBuffer,
+ mMicrocodePointerBuffer,
+ sizeof (EFI_CPU_MICROCODE_HEADER *) * (NUMBER_OF_MICROCODE_UPDATE + 1)
+ );
+
+ mAcpiCpuData->CpuPrivateData = (EFI_PHYSICAL_ADDRESS)(UINTN)(&(mMPSystemData->S3DataPointer));
+ mAcpiCpuData->S3BootPath = FALSE;
+ mAcpiCpuData->MicrocodePointerBuffer = (EFI_PHYSICAL_ADDRESS)(UINTN)(MpCpuReservedData->MicrocodePointerBuffer);
+ mAcpiCpuData->GdtrProfile = (EFI_PHYSICAL_ADDRESS)(UINTN)(&(MpCpuReservedData->GdtrProfile));
+ mAcpiCpuData->IdtrProfile = (EFI_PHYSICAL_ADDRESS)(UINTN)(&(MpCpuReservedData->IdtrProfile));
+
+ MpServiceInitialize ();
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/Ia32/MpProc.asm b/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/Ia32/MpProc.asm
new file mode 100644
index 0000000000..e07056d304
--- /dev/null
+++ b/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/Ia32/MpProc.asm
@@ -0,0 +1,83 @@
+;; @file
+; This is the code that supports MP.
+;
+; Copyright (c) 1999 - 2015, 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.
+;
+;;
+ page ,132
+ title MP ASSEMBLY HOOKS
+.686p
+.model flat
+.data
+.stack
+.code
+.MMX
+.XMM
+_MpMtrrSynchUpEntry PROC NEAR PUBLIC
+ ;
+ ; Enter no fill cache mode, CD=1(Bit30), NW=0 (Bit29)
+ ;
+ mov eax, cr0
+ and eax, 0DFFFFFFFh
+ or eax, 040000000h
+ mov cr0, eax
+ ;
+ ; Flush cache
+ ;
+ wbinvd
+ ;
+ ; Clear PGE flag Bit 7
+ ;
+ mov eax, cr4
+ mov edx, eax
+ and eax, 0FFFFFF7Fh
+ mov cr4, eax
+ ;
+ ; Flush all TLBs
+ ;
+ mov eax, cr3
+ mov cr3, eax
+
+ mov eax, edx
+
+ ret
+
+_MpMtrrSynchUpEntry ENDP
+
+_MpMtrrSynchUpExit PROC NEAR PUBLIC
+
+ push ebp ; C prolog
+ mov ebp, esp
+ ;
+ ; Flush all TLBs the second time
+ ;
+ mov eax, cr3
+ mov cr3, eax
+ ;
+ ; Enable Normal Mode caching CD=NW=0, CD(Bit30), NW(Bit29)
+ ;
+ mov eax, cr0
+ and eax, 09FFFFFFFh
+ mov cr0, eax
+ ;
+ ; Set PGE Flag in CR4 if set
+ ;
+ mov eax, dword ptr [ebp + 8]
+ mov cr4, eax
+
+ pop ebp
+
+ ret
+
+_MpMtrrSynchUpExit ENDP
+
+ END
+
diff --git a/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/Ia32/MpProc.s b/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/Ia32/MpProc.s
new file mode 100644
index 0000000000..73ebd1cf2e
--- /dev/null
+++ b/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/Ia32/MpProc.s
@@ -0,0 +1,69 @@
+## @file
+# This is the code that supports MP.
+#
+# Copyright (c) 1999 - 2015, 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.
+#
+##
+
+ASM_GLOBAL ASM_PFX(MpMtrrSynchUpEntry)
+ASM_PFX(MpMtrrSynchUpEntry):
+ #
+ # Enter no fill cache mode, CD=1(Bit30), NW=0 (Bit29)
+ #
+ movl %cr0, %eax
+ andl 0x0DFFFFFFF, %eax
+ orl 0x040000000, %eax
+ movl %eax, %cr0
+ #
+ # Flush cache
+ #
+ wbinvd
+ #
+ # Clear PGE flag Bit 7
+ #
+ movl %cr4, %eax
+ movl %eax, %edx
+ andl 0x0FFFFFF7F, %eax
+ movl %eax, %cr4
+ #
+ # Flush all TLBs
+ #
+ movl %cr3, %eax
+ movl %eax, %cr3
+
+ movl %edx, %eax
+ ret
+#MpMtrrSynchUpEntry ENDP
+
+ASM_GLOBAL ASM_PFX(MpMtrrSynchUpExit)
+ASM_PFX(MpMtrrSynchUpExit):
+ push %ebp # C prolog
+ movl %esp, %ebp
+ #
+ # Flush all TLBs the second time
+ #
+ movl %cr3, %eax
+ movl %eax, %cr3
+ #
+ # Enable Normal Mode caching CD=NW=0, CD(Bit30), NW(Bit29)
+ #
+ movl %cr0, %eax
+ andl 0x09FFFFFFF, %eax
+ movl %eax, %cr0
+ #
+ # Set PGE Flag in CR4 if set
+ #
+ movl 8(%ebp), %eax
+ movl %eax, %cr4
+
+ pop %ebp
+ ret
+#MpMtrrSynchUpExit ENDP
diff --git a/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/Ia32/ProcessorDef.h b/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/Ia32/ProcessorDef.h
new file mode 100644
index 0000000000..c150ba60b7
--- /dev/null
+++ b/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/Ia32/ProcessorDef.h
@@ -0,0 +1,56 @@
+/** @file
+ Definition for IA32 processor.
+
+ Copyright (c) 2014 - 2015, 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 _PROCESSOR_DEF_H
+#define _PROCESSOR_DEF_H
+
+
+#pragma pack(1)
+/**
+ @todo No structure description
+
+**/
+typedef struct {
+ UINT16 OffsetLow;
+ UINT16 SegmentSelector;
+ UINT16 Attributes;
+ UINT16 OffsetHigh;
+} INTERRUPT_GATE_DESCRIPTOR;
+
+#pragma pack()
+
+/**
+ @todo No structure description
+
+**/
+
+typedef struct {
+ UINT8 *RendezvousFunnelAddress;
+ UINTN PModeEntryOffset;
+ UINTN FlatJumpOffset;
+ UINTN Size;
+} MP_ASSEMBLY_ADDRESS_MAP;
+
+/**
+ Get address map of RendezvousFunnelProc.
+
+ @param[in] AddressMap - Output buffer for address map information
+**/
+VOID
+AsmGetAddressMap (
+ OUT MP_ASSEMBLY_ADDRESS_MAP *AddressMap
+ );
+
+#endif
diff --git a/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/MemoryAttribute.c b/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/MemoryAttribute.c
new file mode 100644
index 0000000000..ddf4f56536
--- /dev/null
+++ b/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/MemoryAttribute.c
@@ -0,0 +1,975 @@
+/** @file
+ The function of Memory Attribute.
+
+ Copyright (c) 1999 - 2015, 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 "CpuDxe.h"
+#include "MemoryAttribute.h"
+
+EFI_FIXED_MTRR mFixedMtrrTable[] = {
+ { EFI_MSR_IA32_MTRR_FIX64K_00000, 0, 0x10000},
+ { EFI_MSR_IA32_MTRR_FIX16K_80000, 0x80000, 0x4000},
+ { EFI_MSR_IA32_MTRR_FIX16K_A0000, 0xA0000, 0x4000},
+ { EFI_MSR_IA32_MTRR_FIX4K_C0000, 0xC0000, 0x1000},
+ { EFI_MSR_IA32_MTRR_FIX4K_C8000, 0xC8000, 0x1000},
+ { EFI_MSR_IA32_MTRR_FIX4K_D0000, 0xD0000, 0x1000},
+ { EFI_MSR_IA32_MTRR_FIX4K_D8000, 0xD8000, 0x1000},
+ { EFI_MSR_IA32_MTRR_FIX4K_E0000, 0xE0000, 0x1000},
+ { EFI_MSR_IA32_MTRR_FIX4K_E8000, 0xE8000, 0x1000},
+ { EFI_MSR_IA32_MTRR_FIX4K_F0000, 0xF0000, 0x1000},
+ { EFI_MSR_IA32_MTRR_FIX4K_F8000, 0xF8000, 0x1000}
+};
+
+EFI_VARIABLE_MTRR mVariableMtrr[6];
+UINT32 mUsedMtrr;
+UINT8 mDefaultMemoryType = EFI_MEMORY_UC;
+extern UINT64 mValidMtrrAddressMask;
+extern UINT64 mValidMtrrBitsMask;
+
+/**
+ @todo Add function description
+
+ @retval @todo add return values
+
+**/
+VOID
+PreMtrrChange (
+ VOID
+ )
+{
+ UINT64 TempQword;
+
+ AsmDisableCache ();
+ //
+ // Disable Cache MTRR
+ //
+ TempQword = AsmReadMsr64 (EFI_MSR_CACHE_IA32_MTRR_DEF_TYPE);
+ TempQword = TempQword & ~B_EFI_MSR_GLOBAL_MTRR_ENABLE & ~B_EFI_MSR_FIXED_MTRR_ENABLE;
+ AsmWriteMsr64 (EFI_MSR_CACHE_IA32_MTRR_DEF_TYPE, TempQword);
+}
+
+/**
+ @todo Add function description
+
+ @retval @todo add return values
+
+**/
+VOID
+PostMtrrChange (
+ VOID
+ )
+{
+ UINT64 TempQword;
+
+ TempQword = 0;
+ //
+ // Enable Cache MTRR
+ //
+ TempQword = AsmReadMsr64 (EFI_MSR_CACHE_IA32_MTRR_DEF_TYPE);
+ AsmWriteMsr64 (EFI_MSR_CACHE_IA32_MTRR_DEF_TYPE, TempQword | B_EFI_MSR_GLOBAL_MTRR_ENABLE | B_EFI_MSR_FIXED_MTRR_ENABLE);
+
+ AsmEnableCache ();
+}
+
+/**
+ @todo Add function description
+
+ @param[in] MemoryCacheType - @todo add argument description
+ @param[in] Base - @todo add argument description
+ @param[in] Length - @todo add argument description
+
+ @retval EFI_UNSUPPORTED - @todo Add description for return value
+ @retval EFI_UNSUPPORTED - @todo Add description for return value
+ @retval EFI_UNSUPPORTED - @todo Add description for return value
+ @retval EFI_SUCCESS - @todo Add description for return value
+
+**/
+EFI_STATUS
+ProgramFixedMtrr (
+ IN UINT64 MemoryCacheType,
+ IN UINT64 *Base,
+ IN UINT64 *Length
+ )
+{
+ UINT32 MsrNum;
+ UINT32 ByteShift;
+ UINT64 TempQword;
+ UINT64 OrMask;
+ UINT64 ClearMask;
+
+ TempQword = 0;
+ OrMask = 0;
+ ClearMask = 0;
+
+ for (MsrNum = 0; MsrNum < V_EFI_FIXED_MTRR_NUMBER; MsrNum++) {
+ if ((*Base >= mFixedMtrrTable[MsrNum].BaseAddress) &&
+ (*Base < (mFixedMtrrTable[MsrNum].BaseAddress + 8 * mFixedMtrrTable[MsrNum].Length))
+ ) {
+ break;
+ }
+ }
+
+ if (MsrNum == V_EFI_FIXED_MTRR_NUMBER) {
+ return EFI_UNSUPPORTED;
+ }
+ //
+ // We found the fixed MTRR to be programmed
+ //
+ for (ByteShift = 0; ByteShift < 8; ByteShift++) {
+ if (*Base == (mFixedMtrrTable[MsrNum].BaseAddress + ByteShift * mFixedMtrrTable[MsrNum].Length)) {
+ break;
+ }
+ }
+
+ if (ByteShift == 8) {
+ return EFI_UNSUPPORTED;
+ }
+
+ for (; ((ByteShift < 8) && (*Length >= mFixedMtrrTable[MsrNum].Length)); ByteShift++) {
+ OrMask |= LShiftU64 ((UINT64) MemoryCacheType, (UINT32) (ByteShift * 8));
+ ClearMask |= LShiftU64 ((UINT64) 0xFF, (UINT32) (ByteShift * 8));
+ *Length -= mFixedMtrrTable[MsrNum].Length;
+ *Base += mFixedMtrrTable[MsrNum].Length;
+ }
+
+ if (ByteShift < 8 && (*Length != 0)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ TempQword = ((AsmReadMsr64 (mFixedMtrrTable[MsrNum].Msr) & ~ClearMask) | OrMask);
+ AsmWriteMsr64 (mFixedMtrrTable[MsrNum].Msr, TempQword);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ @todo Add function description
+
+ @retval EFI_SUCCESS - @todo Add description for return value
+
+**/
+EFI_STATUS
+GetMemoryAttribute (
+ VOID
+ )
+{
+ UINTN Index;
+ UINT32 MsrNum, MsrNumEnd;
+ UINT64 MsrValue;
+
+ //
+ // Get Default Mtrr Type
+ //
+ MsrValue = AsmReadMsr64 (EFI_MSR_CACHE_IA32_MTRR_DEF_TYPE);
+ mDefaultMemoryType = (UINT8) MsrValue;
+
+ //
+ // Get Variable Mtrr
+ //
+ ZeroMem (mVariableMtrr, sizeof (EFI_VARIABLE_MTRR) * 6);
+ mUsedMtrr = 0;
+ MsrNumEnd = EFI_MSR_CACHE_VARIABLE_MTRR_BASE + (2 * (UINT32)(AsmReadMsr64(EFI_MSR_IA32_MTRR_CAP) & B_EFI_MSR_IA32_MTRR_CAP_VARIABLE_SUPPORT));
+ for (MsrNum = EFI_MSR_CACHE_VARIABLE_MTRR_BASE, Index = 0;
+ ((MsrNum < MsrNumEnd) && (Index < 6));
+ MsrNum += 2) {
+ if ((AsmReadMsr64 (MsrNum + 1) & B_EFI_MSR_CACHE_MTRR_VALID) != 0) {
+ mVariableMtrr[Index].Msr = MsrNum;
+ mVariableMtrr[Index].BaseAddress = (AsmReadMsr64 (MsrNum) & mValidMtrrAddressMask);
+ mVariableMtrr[Index].Length = ((~((AsmReadMsr64 (MsrNum + 1) & mValidMtrrAddressMask))) & mValidMtrrBitsMask) + 1;
+ mVariableMtrr[Index].Type = (AsmReadMsr64 (MsrNum) & B_EFI_MSR_CACHE_MEMORY_TYPE);
+ mVariableMtrr[Index].Valid = TRUE;
+ mUsedMtrr++;
+ Index++;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ @todo Add function description
+
+ @param[in] Start - @todo add argument description
+ @param[in] End - @todo add argument description
+
+ @retval - @todo add return values
+
+**/
+BOOLEAN
+CheckMemoryAttributeOverlap (
+ IN EFI_PHYSICAL_ADDRESS Start,
+ IN EFI_PHYSICAL_ADDRESS End
+ )
+{
+ UINT32 Index;
+
+ for (Index = 0; Index < 6; Index++) {
+ if (mVariableMtrr[Index].Valid &&
+ !(
+ Start > (mVariableMtrr[Index].BaseAddress + mVariableMtrr[Index].Length - 1) ||
+ (End < mVariableMtrr[Index].BaseAddress)
+ )
+ ) {
+
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+/**
+ @todo Add function description
+
+ @param[in] Attributes - @todo add argument description
+ @param[in] Base - @todo add argument description
+ @param[in] Length - @todo add argument description
+
+ @retval EFI_SUCCESS - @todo Add description for return value
+ @retval EFI_SUCCESS - @todo Add description for return value
+ @retval EFI_ACCESS_DENIED - @todo Add description for return value
+ @retval EFI_SUCCESS - @todo Add description for return value
+
+**/
+EFI_STATUS
+CombineMemoryAttribute (
+ IN UINT64 Attributes,
+ IN UINT64 *Base,
+ IN UINT64 *Length
+ )
+{
+ UINT32 Index;
+ UINT64 CombineStart;
+ UINT64 CombineEnd;
+ UINT64 MtrrEnd;
+ UINT64 EndAddress;
+ BOOLEAN InvalidMTRRs[6];
+
+ EndAddress = *Base +*Length - 1;
+
+ for (Index = 0; Index < 6; Index++) {
+ InvalidMTRRs[Index] = FALSE;
+ }
+
+ Index = 0;
+ while (Index < 6) {
+ MtrrEnd = mVariableMtrr[Index].BaseAddress + mVariableMtrr[Index].Length - 1;
+
+ //
+ // The MTRR is marked invalid or the ranges are not intersected.
+ //
+ if (InvalidMTRRs[Index] ||
+ !mVariableMtrr[Index].Valid ||
+ (*Base > (MtrrEnd) || (EndAddress < mVariableMtrr[Index].BaseAddress))) {
+ Index++;
+ continue;
+ }
+
+ //
+ // if the requested range contains MTRR range, invalidate this MTRR
+ //
+ if (mVariableMtrr[Index].BaseAddress >= *Base && MtrrEnd <= EndAddress) {
+ InvalidMTRRs[Index] = TRUE;
+ Index++;
+ continue;
+ }
+
+ if (Attributes == mVariableMtrr[Index].Type) {
+ //
+ // if the Mtrr range contain the request range, return EFI_SUCCESS
+ //
+ if (mVariableMtrr[Index].BaseAddress <= *Base && MtrrEnd >= EndAddress) {
+ *Length = 0;
+ return EFI_SUCCESS;
+ }
+
+ //
+ // invalid this MTRR, and program the combine range
+ //
+ CombineStart = (*Base) < mVariableMtrr[Index].BaseAddress ? (*Base) : mVariableMtrr[Index].BaseAddress;
+ CombineEnd = EndAddress > MtrrEnd ? EndAddress : MtrrEnd;
+
+ //
+ // Record this MTRR as invalid
+ //
+ InvalidMTRRs[Index] = TRUE;
+
+ //
+ // The range is modified, retry from the first MTRR
+ //
+ if (*Base != CombineStart || *Length != CombineEnd - CombineStart + 1) {
+ Index = 0;
+ } else {
+ Index++;
+ }
+ *Base = CombineStart;
+ *Length = CombineEnd - CombineStart + 1;
+ EndAddress = CombineEnd;
+ continue;
+ }
+
+ if ((Attributes == EFI_CACHE_UNCACHEABLE) ||
+ (Attributes == EFI_CACHE_WRITETHROUGH && mVariableMtrr[Index].Type == EFI_CACHE_WRITEBACK) ||
+ (Attributes == EFI_CACHE_WRITEBACK && mVariableMtrr[Index].Type == EFI_CACHE_WRITETHROUGH) ||
+ (Attributes == EFI_CACHE_WRITETHROUGH && mVariableMtrr[Index].Type == EFI_CACHE_UNCACHEABLE) ||
+ (Attributes == EFI_CACHE_WRITEBACK && mVariableMtrr[Index].Type == EFI_CACHE_UNCACHEABLE)
+ ) {
+ Index++;
+ continue;
+ }
+
+ //
+ // Other type memory overlap is invalid
+ //
+ return EFI_ACCESS_DENIED;
+ }
+
+ //
+ // Finally invalidate recorded MTRRs
+ //
+ for (Index = 0; Index < 6; Index++) {
+ if (InvalidMTRRs[Index]) {
+ InvariableMtrr (mVariableMtrr[Index].Msr, Index);
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Given the input, check if the number of MTRR is lesser
+ if positive or subtractive
+
+ @param[in] Input - Length of Memory to program MTRR
+ @param[in] MtrrNumber - return needed Mtrr number
+ @param[in] Direction - TRUE: do positive
+ FALSE: do subtractive
+ @retval @todo Return values are defined as:
+ Zero, do positive
+ Non-Zero, do subractive. is this OK?
+ @todo EFI_SUCCESS - add return value to function comment
+
+**/
+EFI_STATUS
+GetDirection (
+ IN UINT64 Input,
+ IN UINTN *MtrrNumber,
+ IN BOOLEAN *Direction
+ )
+{
+ UINT64 TempQword;
+ UINT32 Positive;
+ UINT32 Subtractive;
+
+ TempQword = Input;
+ Positive = 0;
+ Subtractive = 0;
+
+ do {
+ TempQword -= Power2MaxMemory (TempQword);
+ Positive++;
+
+ } while (TempQword != 0);
+
+ TempQword = Power2MaxMemory (LShiftU64 (Input, 1)) - Input;
+ Subtractive++;
+ do {
+ TempQword -= Power2MaxMemory (TempQword);
+ Subtractive++;
+
+ } while (TempQword != 0);
+
+ if (Positive <= Subtractive) {
+ *Direction = TRUE;
+ *MtrrNumber = Positive;
+ } else {
+ *Direction = FALSE;
+ *MtrrNumber = Subtractive;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ @todo Add function description
+
+ @param[in] MemoryLength - @todo add argument description
+
+ @retval @todo add return values
+
+**/
+UINT64
+Power2MaxMemory (
+ IN UINT64 MemoryLength
+ )
+{
+ UINT64 Result;
+
+ if (RShiftU64 (MemoryLength, 32)) {
+ Result = LShiftU64 ((UINT64) GetPowerOfTwo64 ((UINT32) RShiftU64 (MemoryLength, 32)), 32);
+ } else {
+ Result = (UINT64) GetPowerOfTwo64 ((UINT32) MemoryLength);
+ }
+
+ return Result;
+}
+
+/**
+ @todo Add function description
+
+ @param[in] MtrrNumber - @todo add argument description
+ @param[in] Index - @todo add argument description
+
+ @retval EFI_SUCCESS - @todo Add description for return value
+
+**/
+EFI_STATUS
+InvariableMtrr (
+ IN UINTN MtrrNumber,
+ IN UINTN Index
+ )
+{
+ PreMtrrChange ();
+ mVariableMtrr[Index].Valid = FALSE;
+ AsmWriteMsr64 ((UINT32) MtrrNumber, 0);
+ AsmWriteMsr64 ((UINT32) (MtrrNumber + 1), 0);
+ mUsedMtrr--;
+ PostMtrrChange ();
+
+ return EFI_SUCCESS;
+}
+
+/**
+ @todo Add function description
+
+ @param[in] MtrrNumber - @todo add argument description
+ @param[in] BaseAddress - @todo add argument description
+ @param[in] Length - @todo add argument description
+ @param[in] MemoryCacheType - @todo add argument description
+
+ @retval EFI_SUCCESS - @todo Add description for return value
+
+**/
+EFI_STATUS
+ProgramVariableMtrr (
+ IN UINTN MtrrNumber,
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length,
+ IN UINT64 MemoryCacheType
+ )
+{
+ UINT64 TempQword;
+
+ PreMtrrChange ();
+
+ //
+ // MTRR Physical Base
+ //
+ TempQword = (BaseAddress & mValidMtrrAddressMask) | MemoryCacheType;
+ AsmWriteMsr64 ((UINT32) MtrrNumber, TempQword);
+
+ //
+ // MTRR Physical Mask
+ //
+ TempQword = ~(Length - 1);
+ AsmWriteMsr64 ((UINT32) (MtrrNumber + 1), (TempQword & mValidMtrrAddressMask) | B_EFI_MSR_CACHE_MTRR_VALID);
+
+ PostMtrrChange ();
+
+ return EFI_SUCCESS;
+}
+
+/**
+ @todo Add function description
+
+ @retval EFI_SUCCESS - @todo Add description for return value
+ @retval EFI_OUT_OF_RESOURCES - @todo Add description for return value
+ @retval EFI_SUCCESS - @todo Add description for return value
+
+**/
+EFI_STATUS
+CleanupVariableMtrr (
+ VOID
+ )
+{
+ BOOLEAN Cleaned;
+ BOOLEAN EverCleaned;
+ UINTN Index;
+ UINTN Index2;
+ BOOLEAN MtrrModified[6];
+ UINTN MtrrNumber;
+ UINTN MsrNum, MsrNumEnd;
+ EFI_PHYSICAL_ADDRESS BaseAddress;
+ UINT64 Length;
+ UINT64 TempQword;
+ UINT64 Attributes;
+ BOOLEAN Positive;
+
+ for (Index = 0; Index < 6; Index++) {
+ MtrrModified[Index] = FALSE;
+ }
+
+ GetMemoryAttribute ();
+
+ //
+ // After the do-while, mVariableMtrr is NO longer the value read from MTRR regisrer!!!
+ //
+ EverCleaned = FALSE;
+
+ do {
+ Cleaned = FALSE;
+
+ for (Index = 0; Index < 6; Index++) {
+ if (mVariableMtrr[Index].Type == EFI_CACHE_UNCACHEABLE && mVariableMtrr[Index].Valid) {
+ for (Index2 = 0; Index2 < 6; Index2++) {
+ if (mVariableMtrr[Index2].Type == EFI_CACHE_WRITEBACK && mVariableMtrr[Index2].Valid) {
+ //
+ // the Uncacheble just inside the WB and at the edge.
+ // if so, we can clean the UC entry and decrease the WB entry
+ //
+ if (mVariableMtrr[Index].BaseAddress == mVariableMtrr[Index2].BaseAddress) {
+ Cleaned = TRUE;
+ EverCleaned = TRUE;
+ if (mVariableMtrr[Index].Length >= mVariableMtrr[Index2].Length) {
+ //
+ // we can invalidate WB entry, since nothing left
+ //
+ InvariableMtrr (mVariableMtrr[Index2].Msr, Index2);
+ mVariableMtrr[Index].BaseAddress = mVariableMtrr[Index].BaseAddress + mVariableMtrr[Index2].Length;
+ mVariableMtrr[Index].Length -= mVariableMtrr[Index2].Length;
+ MtrrModified[Index] = TRUE;
+ if (mVariableMtrr[Index].Length == 0) {
+ InvariableMtrr (mVariableMtrr[Index].Msr, Index);
+ }
+
+ } else {
+ //
+ // we can invalidate UC entry, since nothing left
+ //
+ InvariableMtrr (mVariableMtrr[Index].Msr, Index);
+ mVariableMtrr[Index2].BaseAddress = mVariableMtrr[Index].BaseAddress + mVariableMtrr[Index].Length;
+ mVariableMtrr[Index2].Length -= mVariableMtrr[Index].Length;
+ MtrrModified[Index2] = TRUE;
+ }
+
+ }
+
+ if (mVariableMtrr[Index].BaseAddress +
+ mVariableMtrr[Index].Length == mVariableMtrr[Index2].BaseAddress +
+ mVariableMtrr[Index2].Length
+ ) {
+ Cleaned = TRUE;
+ EverCleaned = TRUE;
+
+ if (mVariableMtrr[Index].Length >= mVariableMtrr[Index2].Length) {
+ //
+ // we can invalidate WB entry, since nothing left
+ //
+ InvariableMtrr (mVariableMtrr[Index2].Msr, Index2);
+ mVariableMtrr[Index].Length -= mVariableMtrr[Index2].Length;
+ MtrrModified[Index] = TRUE;
+ if (mVariableMtrr[Index].Length == 0) {
+ InvariableMtrr (mVariableMtrr[Index].Msr, Index);
+ }
+
+ } else {
+ //
+ // we can invalidate UC entry, since nothing left
+ //
+ InvariableMtrr (mVariableMtrr[Index].Msr, Index);
+ mVariableMtrr[Index2].Length -= mVariableMtrr[Index].Length;
+ MtrrModified[Index2] = TRUE;
+ }
+
+ }
+ }
+ //
+ // end WB
+ //
+ }
+ //
+ // end of Index2
+ //
+ }
+ //
+ // Endof UC
+ //
+ }
+ //
+ // endof Index
+ //
+ } while (Cleaned);
+
+ if (!EverCleaned) {
+ return EFI_SUCCESS;
+ }
+
+ MsrNumEnd = EFI_MSR_CACHE_VARIABLE_MTRR_BASE + (2 * (UINT32)(AsmReadMsr64(EFI_MSR_IA32_MTRR_CAP) & B_EFI_MSR_IA32_MTRR_CAP_VARIABLE_SUPPORT));
+
+ //
+ // Begin to program the MTRR again
+ //
+ for (Index = 0; Index < 6; Index++) {
+ if (MtrrModified[Index] && mVariableMtrr[Index].Valid) {
+ //
+ // Program the new MTRR
+ //
+ TempQword = mVariableMtrr[Index].Length;
+ MsrNum = EFI_MSR_CACHE_VARIABLE_MTRR_BASE + 2 * Index;
+ BaseAddress = mVariableMtrr[Index].BaseAddress;
+ Length = mVariableMtrr[Index].Length;
+ Attributes = mVariableMtrr[Index].Type;
+
+ if (TempQword == Power2MaxMemory (TempQword)) {
+ //
+ // if it's two's power
+ // no need to request a new mtrr,
+ // just program this one
+ //
+ ProgramVariableMtrr (
+ MsrNum,
+ BaseAddress,
+ Length,
+ Attributes
+ );
+ } else {
+ GetDirection (TempQword, &MtrrNumber, &Positive);
+ //
+ // we already has one that can use, so 6+1
+ //
+ if ((mUsedMtrr + MtrrNumber) > 6 + 1) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ if (!Positive) {
+ Length = Power2MaxMemory (LShiftU64 (TempQword, 1));
+ ProgramVariableMtrr (
+ MsrNum,
+ BaseAddress,
+ Length,
+ Attributes
+ );
+ BaseAddress += TempQword;
+ TempQword = Length - TempQword;
+ Attributes = EFI_CACHE_UNCACHEABLE;
+ }
+
+ do {
+ //
+ // Find unused MTRR
+ //
+ for (MsrNum = EFI_MSR_CACHE_VARIABLE_MTRR_BASE; MsrNum < MsrNumEnd; MsrNum += 2) {
+ if ((AsmReadMsr64 ((UINT32) (MsrNum + 1)) & B_EFI_MSR_CACHE_MTRR_VALID) == 0) {
+ break;
+ }
+ }
+
+ Length = Power2MaxMemory (TempQword);
+ ProgramVariableMtrr (
+ MsrNum,
+ BaseAddress,
+ Length,
+ Attributes
+ );
+ BaseAddress += Length;
+ TempQword -= Length;
+
+ } while (TempQword);
+
+ }
+ //
+ // endof Powerof
+ //
+ }
+ //
+ // endof Modified
+ //
+ }
+ //
+ // endof for
+ //
+ return EFI_SUCCESS;
+}
+
+/**
+ Get GCD Mem Space type from Mtrr Type.
+
+ @param[in] MtrrAttribute - Mtrr type
+
+ @retval GCD Mem Space typed (64-bit)
+
+**/
+UINT64
+GetMemorySpaceAttributeFromMtrrType (
+ IN UINT8 MtrrAttributes
+ )
+{
+ switch (MtrrAttributes) {
+ case EFI_CACHE_UNCACHEABLE:
+ return EFI_MEMORY_UC;
+ case EFI_CACHE_WRITECOMBINING:
+ return EFI_MEMORY_WC;
+ case EFI_CACHE_WRITETHROUGH:
+ return EFI_MEMORY_WT;
+ case EFI_CACHE_WRITEPROTECTED:
+ return EFI_MEMORY_WP;
+ case EFI_CACHE_WRITEBACK:
+ return EFI_MEMORY_WB;
+ default:
+ return 0;
+ }
+}
+
+/**
+ Refresh the GCD Memory Space Attributes according to MTRRs
+
+**/
+EFI_STATUS
+RefreshGcdMemoryAttributes (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ UINTN SubIndex;
+ UINT64 RegValue;
+ EFI_PHYSICAL_ADDRESS BaseAddress;
+ UINT64 Length;
+ UINT64 Attributes;
+ UINT64 CurrentAttributes;
+ UINT8 MtrrType;
+ UINTN NumberOfDescriptors;
+ EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap;
+ UINT64 DefaultAttributes;
+
+ MemorySpaceMap = NULL;
+
+ Status = GetMemoryAttribute ();
+ if (EFI_ERROR(Status)) {
+ goto Done;
+ }
+
+ Status = gDS->GetMemorySpaceMap (
+ &NumberOfDescriptors,
+ &MemorySpaceMap
+ );
+ if (EFI_ERROR(Status)) {
+ goto Done;
+ }
+
+ DefaultAttributes = GetMemorySpaceAttributeFromMtrrType (mDefaultMemoryType);
+
+ //
+ // Set default attributes to all spaces.
+ //
+ for (Index = 0; Index < NumberOfDescriptors; Index++) {
+ if (MemorySpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeNonExistent) {
+ continue;
+ }
+ gDS->SetMemorySpaceAttributes (
+ MemorySpaceMap[Index].BaseAddress,
+ MemorySpaceMap[Index].Length,
+ ((MemorySpaceMap[Index].Attributes & ~EFI_MEMORY_CACHETYPE_MASK) |
+ (MemorySpaceMap[Index].Capabilities & DefaultAttributes))
+ );
+ }
+
+ //
+ // Go for variable MTRRs, WB first, Other types second
+ //
+ for (Index = 0; Index < 6; Index++) {
+ if (mVariableMtrr[Index].Valid &&
+ mVariableMtrr[Index].Type == EFI_CACHE_WRITEBACK) {
+ SetGcdMemorySpaceAttributes (
+ MemorySpaceMap,
+ NumberOfDescriptors,
+ mVariableMtrr[Index].BaseAddress,
+ mVariableMtrr[Index].Length,
+ EFI_MEMORY_WB
+ );
+ }
+ }
+ for (Index = 0; Index < 6; Index++) {
+ if (mVariableMtrr[Index].Valid &&
+ mVariableMtrr[Index].Type != EFI_CACHE_WRITEBACK) {
+ Attributes = GetMemorySpaceAttributeFromMtrrType ((UINT8) mVariableMtrr[Index].Type);
+ SetGcdMemorySpaceAttributes (
+ MemorySpaceMap,
+ NumberOfDescriptors,
+ mVariableMtrr[Index].BaseAddress,
+ mVariableMtrr[Index].Length,
+ Attributes
+ );
+ }
+ }
+
+ //
+ // Go for fixed MTRRs
+ //
+ Attributes = 0;
+ BaseAddress = 0;
+ Length = 0;
+ for (Index = 0; Index < V_EFI_FIXED_MTRR_NUMBER; Index++) {
+ RegValue = AsmReadMsr64 (mFixedMtrrTable[Index].Msr);
+ for (SubIndex = 0; SubIndex < 8; SubIndex++) {
+ MtrrType = (UINT8) RShiftU64 (RegValue, SubIndex * 8);
+ CurrentAttributes = GetMemorySpaceAttributeFromMtrrType (MtrrType);
+ if (Length == 0) {
+ Attributes = CurrentAttributes;
+ } else {
+ if (CurrentAttributes != Attributes) {
+ SetGcdMemorySpaceAttributes (
+ MemorySpaceMap,
+ NumberOfDescriptors,
+ BaseAddress,
+ Length,
+ Attributes
+ );
+ BaseAddress = mFixedMtrrTable[Index].BaseAddress + mFixedMtrrTable[Index].Length * SubIndex;
+ Length = 0;
+ Attributes = CurrentAttributes;
+ }
+ }
+ Length += mFixedMtrrTable[Index].Length;
+ }
+ }
+ //
+ // handle the last region
+ //
+ SetGcdMemorySpaceAttributes (
+ MemorySpaceMap,
+ NumberOfDescriptors,
+ BaseAddress,
+ Length,
+ Attributes
+ );
+
+ Done:
+ if (MemorySpaceMap != NULL) {
+ gBS->FreePool (MemorySpaceMap);
+ }
+
+ return Status;
+}
+
+/**
+ Search into the Gcd Memory Space for descriptors (from StartIndex
+ to EndIndex) that contains the memory range specified by BaseAddress
+ and Length.
+
+ @param[in] MemorySpaceMap Gcd Memory Space Map as array
+ @param[in] NumberOfDescriptors Number of descriptors in map
+ @param[in] BaseAddress BaseAddress for the requested range
+ @param[in] Length Length for the requested range
+ @param[out] *StartIndex Start index into the Gcd Memory Space Map
+ @param[out] *EndIndex End index into the Gcd Memory Space Map
+
+ @retval EFI_SUCCESS Search successfully
+ @retval EFI_NOT_FOUND The requested descriptors not exist
+
+**/
+EFI_STATUS
+SearchGcdMemorySpaces (
+ IN EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap,
+ IN UINTN NumberOfDescriptors,
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length,
+ OUT UINTN *StartIndex,
+ OUT UINTN *EndIndex
+ )
+{
+ UINTN Index;
+
+ *StartIndex = 0;
+ *EndIndex = 0;
+
+ for (Index = 0; Index < NumberOfDescriptors; Index++) {
+ if (BaseAddress >= MemorySpaceMap[Index].BaseAddress &&
+ BaseAddress < MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length) {
+ *StartIndex = Index;
+ }
+ if (BaseAddress + Length - 1 >= MemorySpaceMap[Index].BaseAddress &&
+ BaseAddress + Length - 1 < MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length) {
+ *EndIndex = Index;
+ return EFI_SUCCESS;
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+/**
+ Set the attributes for a specified range in Gcd Memory Space Map.
+
+ @param[in] MemorySpaceMap Gcd Memory Space Map as array
+ @param[in] NumberOfDescriptors Number of descriptors in map
+ @param[in] BaseAddress BaseAddress for the range
+ @param[in] Length Length for the range
+ @param[in] Attributes Attributes to set
+
+ @retval EFI_SUCCESS Set successfully
+ @retval EFI_NOT_FOUND The specified range does not exist in Gcd Memory Space
+
+**/
+EFI_STATUS
+SetGcdMemorySpaceAttributes (
+ IN EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap,
+ IN UINTN NumberOfDescriptors,
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length,
+ IN UINT64 Attributes
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ UINTN StartIndex;
+ UINTN EndIndex;
+ EFI_PHYSICAL_ADDRESS RegionStart;
+ UINT64 RegionLength;
+
+ Status = SearchGcdMemorySpaces (
+ MemorySpaceMap,
+ NumberOfDescriptors,
+ BaseAddress,
+ Length,
+ &StartIndex,
+ &EndIndex
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ for (Index = StartIndex; Index <= EndIndex; Index++) {
+ if (MemorySpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeNonExistent) {
+ continue;
+ }
+ if (BaseAddress >= MemorySpaceMap[Index].BaseAddress) {
+ RegionStart = BaseAddress;
+ } else {
+ RegionStart = MemorySpaceMap[Index].BaseAddress;
+ }
+ if (BaseAddress + Length - 1 < MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length) {
+ RegionLength = BaseAddress + Length - RegionStart;
+ } else {
+ RegionLength = MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length - RegionStart;
+ }
+ gDS->SetMemorySpaceAttributes (
+ RegionStart,
+ RegionLength,
+ ((MemorySpaceMap[Index].Attributes & ~EFI_MEMORY_CACHETYPE_MASK) |
+ (MemorySpaceMap[Index].Capabilities & Attributes))
+ );
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/MemoryAttribute.h b/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/MemoryAttribute.h
new file mode 100644
index 0000000000..eb70d66252
--- /dev/null
+++ b/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/MemoryAttribute.h
@@ -0,0 +1,136 @@
+/** @file
+ The definition of Memory Attribute.
+
+ Copyright (c) 1999 - 2015, 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 _EFI_MEMORY_ATTRIB_H
+#define _EFI_MEMORY_ATTRIB_H
+
+extern UINT32 mUsedMtrr;
+/**
+ @todo add description
+
+**/
+typedef struct {
+ UINT32 Msr;
+ UINT32 BaseAddress;
+ UINT32 Length;
+} EFI_FIXED_MTRR;
+/**
+ @todo add description
+
+**/
+typedef struct {
+ UINT64 BaseAddress;
+ UINT64 Length;
+ UINT64 Type;
+ UINT32 Msr;
+ BOOLEAN Valid;
+} EFI_VARIABLE_MTRR;
+
+#define EFI_MEMORY_CACHETYPE_MASK (EFI_MEMORY_UC | EFI_MEMORY_WC | EFI_MEMORY_WT | EFI_MEMORY_WB | EFI_MEMORY_UCE)
+
+EFI_STATUS
+ProgramFixedMtrr (
+ IN UINT64 MemoryCacheType,
+ IN UINT64 *Base,
+ IN UINT64 *Length
+ );
+
+VOID
+PreMtrrChange (
+ VOID
+ );
+VOID
+PostMtrrChange (
+ VOID
+ );
+
+EFI_STATUS
+GetMemoryAttribute (
+ VOID
+ );
+
+BOOLEAN
+CheckMemoryAttributeOverlap (
+ IN EFI_PHYSICAL_ADDRESS Start,
+ IN EFI_PHYSICAL_ADDRESS End
+ );
+
+EFI_STATUS
+CombineMemoryAttribute (
+ IN UINT64 Attribute,
+ IN UINT64 *Base,
+ IN UINT64 *Length
+ );
+
+EFI_STATUS
+GetDirection (
+ IN UINT64 Input,
+ IN UINTN *MtrrNumber,
+ IN BOOLEAN *Direction
+ );
+
+UINT64
+Power2MaxMemory (
+ IN UINT64 MemoryLength
+ );
+
+EFI_STATUS
+InvariableMtrr (
+ IN UINTN MtrrNumber,
+ IN UINTN Index
+ );
+
+EFI_STATUS
+ProgramVariableMtrr (
+ IN UINTN MtrrNumber,
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length,
+ IN UINT64 MemoryCacheType
+ );
+
+EFI_STATUS
+CleanupVariableMtrr (
+ VOID
+ );
+
+UINT64
+GetMemorySpaceAttributeFromMtrrType (
+ IN UINT8 MtrrAttribute
+ );
+
+EFI_STATUS
+RefreshGcdMemoryAttributes (
+ VOID
+ );
+
+EFI_STATUS
+SearchGcdMemorySpaces (
+ IN EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap,
+ IN UINTN NumberOfDescriptors,
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length,
+ OUT UINTN *StartIndex,
+ OUT UINTN *EndIndex
+ );
+
+EFI_STATUS
+SetGcdMemorySpaceAttributes (
+ IN EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap,
+ IN UINTN NumberOfDescriptors,
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length,
+ IN UINT64 Attributes
+ );
+#endif
diff --git a/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/Microcode.c b/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/Microcode.c
new file mode 100644
index 0000000000..61b7227a4e
--- /dev/null
+++ b/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/Microcode.c
@@ -0,0 +1,483 @@
+/** @file
+ The function of Microcode.
+
+ Copyright (c) 1999 - 2015, 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 "CpuDxe.h"
+#include "MpCommon.h"
+
+//
+// Array of pointers which each points to 1 microcode update binary (in memory)
+//
+EFI_CPU_MICROCODE_HEADER **mMicrocodePointerBuffer;
+BOOLEAN mVerifyMicrocodeChecksum = TRUE;
+
+//
+// Function declaration
+//
+EFI_STATUS
+FindLoadMicrocode (
+ IN UINT32 Cpuid,
+ IN EFI_CPU_MICROCODE_HEADER **MicrocodePointerBuffer,
+ IN OUT UINT32 *Revision
+ );
+
+/**
+ Returns the processor microcode revision of the processor installed in the system.
+
+ @retval Processor Microcode Revision
+
+**/
+UINT32
+GetCpuUcodeRevision (
+ VOID
+ )
+{
+ AsmWriteMsr64 (EFI_MSR_IA32_BIOS_SIGN_ID, 0);
+ AsmCpuid (EFI_CPUID_VERSION_INFO, NULL, NULL, NULL, NULL);
+ return (UINT32) RShiftU64 (AsmReadMsr64 (EFI_MSR_IA32_BIOS_SIGN_ID), 32);
+}
+
+/**
+ This will locate a processor microcode and if it finds a newer revision, it will
+ load it to the processor.
+
+ @param[in] MicrocodePointerBuffer The Array of pointers which each points to 1 microcode update binary (in memory)
+ @param[out] FailedRevision The microcode revision that fails to be loaded
+ @param[in] IsBsp Add parameter description
+
+ @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 EFI_CPU_MICROCODE_HEADER **MicrocodePointerBuffer,
+ OUT UINT32 *FailedRevision,
+ IN BOOLEAN IsBsp
+ )
+{
+ EFI_STATUS Status;
+ UINT32 Cpuid_RegEax;
+ UINT32 UcodeRevision;
+
+ AsmCpuid (EFI_CPUID_VERSION_INFO, &Cpuid_RegEax, NULL, NULL, NULL);
+
+ if (IsBsp) {
+ //
+ // Force Microcode to be loaded for BSP anyway
+ //
+ UcodeRevision = 0;
+ } else {
+ UcodeRevision = GetCpuUcodeRevision ();
+ }
+
+ Status = FindLoadMicrocode (Cpuid_RegEax, MicrocodePointerBuffer, &UcodeRevision);
+ *FailedRevision = UcodeRevision;
+
+ return Status;
+}
+
+/**
+ This will load the microcode to all the processors.
+
+ @param[in] MicrocodeEntryPoint The microcode update pointer
+ @param[in] Revision The current (before load this microcode update) microcode revision
+
+ @retval EFI_SUCCESS Microcode loaded
+ @retval EFI_LOAD_ERROR Microcode not loaded
+
+**/
+EFI_STATUS
+LoadMicrocode (
+ IN EFI_CPU_MICROCODE_HEADER *MicrocodeEntryPoint,
+ IN UINT32 *Revision
+ )
+{
+ //
+ // Load the Processor Microcode
+ //
+ AsmWriteMsr64 (
+ EFI_MSR_IA32_BIOS_UPDT_TRIG,
+ (UINT64) ((UINTN) MicrocodeEntryPoint + sizeof (EFI_CPU_MICROCODE_HEADER))
+ );
+
+ //
+ // Verify that the microcode has been loaded
+ //
+ if (GetCpuUcodeRevision () == *Revision) {
+ return EFI_LOAD_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Verify the DWORD type checksum
+
+ @param[in] ChecksumAddr The start address to be checkumed
+ @param[in] ChecksumType The type of data to be checksumed
+
+ @retval EFI_SUCCESS Checksum correct
+ @retval EFI_CRC_ERROR Checksum incorrect
+
+**/
+EFI_STATUS
+Checksum32Verify (
+ IN UINT32 *ChecksumAddr,
+ IN UINT32 ChecksumLen
+ )
+{
+ UINT32 Checksum;
+ UINT32 Index;
+
+ Checksum = 0;
+
+ for (Index = 0; Index < ChecksumLen; Index ++) {
+ Checksum += ChecksumAddr[Index];
+ }
+
+ return (Checksum == 0) ? EFI_SUCCESS : EFI_CRC_ERROR;
+}
+
+/**
+ This will locate a processor microcode and if it finds a newer revision, it will
+ load it to the processor.
+
+ @param[in] Cpuid Data returned by cpuid instruction
+ @param[in] **MicrocodePointerBuffer The Array of pointers which each points to 1 microcode update binary (in memory)
+ @param[in, out] *Revision As input parameter, the current microcode revision;
+ as output parameter, the microcode revision after microcode update is loaded
+
+ @retval EFI_SUCCESS A new microcode update is loaded
+ @retval Other Due to some reason, no new microcode update is loaded
+
+**/
+EFI_STATUS
+FindLoadMicrocode (
+ IN UINT32 Cpuid,
+ IN EFI_CPU_MICROCODE_HEADER **MicrocodePointerBuffer,
+ IN OUT UINT32 *Revision
+ )
+{
+ EFI_STATUS Status;
+ EFI_CPU_MICROCODE_HEADER *MicrocodeEntryPoint;
+ UINT8 Index;
+ UINT8 Index2;
+ UINT8 MsrPlatform;
+ UINT32 ExtendedTableLength;
+ UINT32 ExtendedTableCount;
+ BOOLEAN CorrectMicrocode;
+ EFI_CPU_MICROCODE_EXTENDED_TABLE *ExtendedTable;
+ EFI_CPU_MICROCODE_EXTENDED_TABLE_HEADER *ExtendedTableHeader;
+
+ Status = EFI_NOT_FOUND;
+ ExtendedTableLength = 0;
+
+ //
+ // The index of platform information resides in bits 50:52 of MSR IA32_PLATFORM_ID
+ //
+ MsrPlatform = (UINT8) (RShiftU64 ((AsmReadMsr64 (EFI_MSR_IA32_PLATFORM_ID) & B_EFI_MSR_IA32_PLATFORM_ID_PLATFORM_ID_BITS_MASK), \
+ N_EFI_MSR_IA32_PLATFORM_ID_PLATFORM_ID_BITS));
+
+ Index = 0;
+ while (MicrocodePointerBuffer[Index] != NULL) {
+ MicrocodeEntryPoint = MicrocodePointerBuffer[Index];
+ CorrectMicrocode = FALSE;
+ //
+ // Check if the microcode is for the Cpu and the version is newer
+ // and the update can be processed on the platform
+ //
+ if (MicrocodeEntryPoint->HeaderVersion == 0x00000001) {
+ if ((MicrocodeEntryPoint->ProcessorId == Cpuid) &&
+ (MicrocodeEntryPoint->UpdateRevision >= *Revision) &&
+ (MicrocodeEntryPoint->ProcessorFlags & (1 << MsrPlatform)) ) {
+ if (mVerifyMicrocodeChecksum == TRUE) {
+ if (MicrocodeEntryPoint->DataSize == 0) {
+ Status = Checksum32Verify ((UINT32 *)MicrocodeEntryPoint, 2048 / sizeof(UINT32));
+ } else {
+ Status = Checksum32Verify ((UINT32 *)MicrocodeEntryPoint, (MicrocodeEntryPoint->DataSize + sizeof(EFI_CPU_MICROCODE_HEADER)) / sizeof(UINT32));
+ }
+ if (!EFI_ERROR (Status)) {
+ mVerifyMicrocodeChecksum = FALSE;
+ CorrectMicrocode = TRUE;
+ }
+ } else {
+ CorrectMicrocode = TRUE;
+ }
+ } else if ((MicrocodeEntryPoint->DataSize !=0) && (MicrocodeEntryPoint->UpdateRevision > *Revision)) {
+ //
+ // Check the Extended Signature if the entended signature exist
+ // Only the data size != 0 the extended signature may exist
+ //
+ ExtendedTableLength = MicrocodeEntryPoint->TotalSize - (MicrocodeEntryPoint->DataSize + sizeof (EFI_CPU_MICROCODE_HEADER));
+ if (ExtendedTableLength != 0) {
+ //
+ // Extended Table exist, check if the CPU in support list
+ //
+ ExtendedTableHeader = (EFI_CPU_MICROCODE_EXTENDED_TABLE_HEADER *)((UINT8 *)(MicrocodeEntryPoint) + MicrocodeEntryPoint->DataSize + 48);
+ //
+ // Calulate Extended Checksum
+ //
+ if ((ExtendedTableLength % 4) == 0) {
+ Status = Checksum32Verify ((UINT32 *)ExtendedTableHeader, ExtendedTableLength / sizeof(UINT32));
+ if (!EFI_ERROR (Status)) {
+ //
+ // Checksum correct
+ //
+ ExtendedTableCount = ExtendedTableHeader->ExtendedSignatureCount;
+ ExtendedTable = (EFI_CPU_MICROCODE_EXTENDED_TABLE *)(ExtendedTableHeader + 1);
+ for (Index2 = 0; Index2 < ExtendedTableCount; Index2 ++) {
+ Status = Checksum32Verify ((UINT32 *)ExtendedTable, sizeof(EFI_CPU_MICROCODE_EXTENDED_TABLE) / sizeof(UINT32));
+ if (!EFI_ERROR (Status)) {
+ //
+ // Verify Header
+ //
+ if ((ExtendedTable->ProcessorSignature == Cpuid) &&
+ (ExtendedTable->ProcessorFlag & (1 << MsrPlatform)) ) {
+ //
+ // Find one
+ //
+ CorrectMicrocode = TRUE;
+ break;
+ }
+ }
+ ExtendedTable ++;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (CorrectMicrocode) {
+ Status = LoadMicrocode (MicrocodeEntryPoint, Revision);
+ *Revision = MicrocodeEntryPoint->UpdateRevision;
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ Index++;
+ }
+
+ return Status;
+}
+
+/**
+ Get the microcode patch.
+
+ @param[in] This Driver context.
+ @param[out] MicrocodeData Retrieved image of the microcode.
+
+ @retval EFI_SUCCESS Image found.
+ @retval EFI_NOT_FOUND Image not found.
+
+**/
+EFI_STATUS
+EFIAPI
+PlatformCpuRetrieveMicrocode (
+ OUT UINT8 **MicrocodeData
+ )
+{
+ EFI_CPU_MICROCODE_HEADER *Microcode;
+ UINTN MicrocodeStart;
+ UINTN MicrocodeEnd;
+ UINTN TotalSize;
+
+ DEBUG ((EFI_D_INFO, "PcdFlashMicroCodeRegionBase - 0x%x\n", PcdGet32 (PcdFlashMicroCodeRegionBase)));
+ DEBUG ((EFI_D_INFO, "PcdFlashMicroCodeOffset - 0x%x\n", PcdGet32 (PcdFlashMicroCodeOffset)));
+ DEBUG ((EFI_D_INFO, "PcdFlashMicroCodeRegionSize - 0x%x\n", PcdGet32 (PcdFlashMicroCodeRegionSize)));
+
+ MicrocodeStart =(UINTN)PcdGet32 (PcdFlashMicroCodeRegionBase) + PcdGet32 (PcdFlashMicroCodeOffset);
+ MicrocodeEnd = (UINTN)PcdGet32 (PcdFlashMicroCodeRegionBase) + (UINTN)PcdGet32 (PcdFlashMicroCodeRegionSize);
+
+ if (*MicrocodeData == NULL) {
+ *MicrocodeData = (UINT8 *) (UINTN) MicrocodeStart;
+ } else {
+ if (*MicrocodeData < (UINT8 *) (UINTN) MicrocodeStart) {
+ return EFI_NOT_FOUND;
+ }
+
+ TotalSize = (UINTN) (((EFI_CPU_MICROCODE_HEADER *) *MicrocodeData)->TotalSize);
+ if (TotalSize == 0) {
+ TotalSize = 2048;
+ }
+ //
+ // Add alignment check - begin
+ //
+ if ((TotalSize & 0x7FF) != 0) {
+ TotalSize = (TotalSize & 0xFFFFF800) + 0x800;
+ }
+ //
+ // Add alignment check - end
+ //
+ *MicrocodeData += TotalSize;
+ Microcode = (EFI_CPU_MICROCODE_HEADER *) *MicrocodeData;
+ if (*MicrocodeData >= (UINT8 *) (UINTN) (MicrocodeEnd) || Microcode->TotalSize == (UINT32) -1) {
+ return EFI_NOT_FOUND;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Load all microcode updates to memory. Since in S3 resume boot path, CPUs should be
+ patched again, these microcode updates are copied to OS reserved memory.
+
+ @retval EFI_SUCCESS All microcode updates are loaded to memory successfully
+ @retval EFI_OUT_OF_RESOURCES Not enough memory to accomodate all the microcode updates
+
+**/
+EFI_STATUS
+LoadAllMicrocodeUpdates (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_CPU_MICROCODE_HEADER *MicrocodeEntryPoint;
+ EFI_CPU_MICROCODE_HEADER *MicrocodeBuffer;
+ UINTN MicrocodeNumber;
+ UINTN Index;
+ UINTN TotalSize[NUMBER_OF_MICROCODE_UPDATE + 1];
+
+ MicrocodeNumber = 0;
+ Status = gBS->AllocatePool (
+ EfiACPIMemoryNVS,
+ sizeof (EFI_CPU_MICROCODE_HEADER *) * (NUMBER_OF_MICROCODE_UPDATE + 1),
+ (VOID *) (&mMicrocodePointerBuffer)
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ ZeroMem (mMicrocodePointerBuffer, sizeof (EFI_CPU_MICROCODE_HEADER *) * (NUMBER_OF_MICROCODE_UPDATE + 1));
+ ZeroMem (TotalSize, sizeof(TotalSize));
+
+ MicrocodeEntryPoint = NULL;
+ MicrocodeBuffer = NULL;
+ while (TRUE) {
+ //
+ // Continue to try to find patch
+ //
+ Status = PlatformCpuRetrieveMicrocode ((VOID *) &MicrocodeEntryPoint);
+
+ if (EFI_ERROR (Status)) {
+ if (Status == EFI_NOT_FOUND) {
+ Status = EFI_SUCCESS;
+ }
+ break;
+
+ } else {
+ if (MicrocodeNumber >= NUMBER_OF_MICROCODE_UPDATE) {
+ DEBUG ((EFI_D_ERROR, "CPU Too Many Microcode available > %d\n", (UINTN)NUMBER_OF_MICROCODE_UPDATE));
+ Status = EFI_SUCCESS;
+ break;
+ }
+
+ if (MicrocodeEntryPoint->DataSize == 0) {
+ TotalSize[MicrocodeNumber] = 2048;
+ } else {
+ TotalSize[MicrocodeNumber] = MicrocodeEntryPoint->TotalSize;
+ }
+
+ Status = AllocateReservedMemoryBelow4G (
+ TotalSize[MicrocodeNumber],
+ (VOID **) &MicrocodeBuffer
+ );
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+
+ CopyMem (MicrocodeBuffer, MicrocodeEntryPoint, TotalSize[MicrocodeNumber]);
+ mMicrocodePointerBuffer[MicrocodeNumber] = MicrocodeBuffer;
+ MicrocodeNumber++;
+ }
+ }
+
+ if (EFI_ERROR (Status)) {
+ Index = 0;
+ while (mMicrocodePointerBuffer[Index] != NULL) {
+ gBS->FreePages (
+ (EFI_PHYSICAL_ADDRESS)(UINTN)mMicrocodePointerBuffer[Index],
+ EFI_SIZE_TO_PAGES(TotalSize[Index])
+ );
+ mMicrocodePointerBuffer[Index] = NULL;
+ Index++;
+ }
+ }
+
+ return Status;
+}
+
+/**
+ Check if loading microcode update fails, if so, report proper status code
+
+ @param[in] CpuNumber The CPU number
+ @param[in] Status The return value of InitializeMicrocode()
+ @param[in] FailedRevision The revision of the microcode update that failed to be loaded
+
+ @retval EFI_SUCCESS The status is check and proper status code is reported
+
+**/
+EFI_STATUS
+CheckMicrocodeUpdate (
+ IN UINTN CpuNumber,
+ IN EFI_STATUS Status,
+ IN UINT32 FailedRevision
+ )
+{
+ EFI_STATUS_CODE_VALUE StatusCode;
+ EFI_STATUS_CODE_DATA *ErrorDataPointer;
+ EFI_COMPUTING_UNIT_MICROCODE_UPDATE_ERROR_DATA ErrorData;
+ UINTN DataSize;
+ if (!EFI_ERROR (Status)) {
+ return EFI_SUCCESS;
+ }
+
+ if (Status == EFI_LOAD_ERROR) {
+ ErrorData.DataHeader.HeaderSize = sizeof (EFI_STATUS_CODE_DATA);
+ ErrorData.DataHeader.Size = sizeof (EFI_COMPUTING_UNIT_MICROCODE_UPDATE_ERROR_DATA) - sizeof (EFI_STATUS_CODE_DATA);
+
+ CopyMem (&ErrorData.DataHeader.Type, &gEfiStatusCodeSpecificDataGuid, sizeof (EFI_GUID));
+ ErrorData.Version = FailedRevision;
+ StatusCode = EFI_COMPUTING_UNIT_HOST_PROCESSOR | EFI_CU_HP_EC_MICROCODE_UPDATE;
+ ErrorDataPointer = (EFI_STATUS_CODE_DATA *) &ErrorData;
+ } else if (Status == EFI_NOT_FOUND) {
+ if (GetCpuUcodeRevision () != 0) {
+ //
+ // Some other driver (for example, SEC) already updated CPU microcode
+ //
+ return EFI_SUCCESS;
+ }
+
+ StatusCode = EFI_COMPUTING_UNIT_HOST_PROCESSOR | EFI_CU_HP_EC_NO_MICROCODE_UPDATE;
+ ErrorDataPointer = NULL;
+
+ } else {
+ return Status;
+ }
+ if (ErrorDataPointer == NULL) {
+ DataSize = 0;
+ } else {
+ DataSize = sizeof(EFI_COMPUTING_UNIT_MICROCODE_UPDATE_ERROR_DATA);
+ }
+ return REPORT_STATUS_CODE_EX (
+ EFI_ERROR_MINOR | EFI_ERROR_CODE,
+ StatusCode,
+ (UINT32) CpuNumber,
+ &gEfiCallerIdGuid,
+ NULL,
+ ErrorDataPointer,
+ DataSize
+ );
+}
diff --git a/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/MiscFuncs.c b/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/MiscFuncs.c
new file mode 100644
index 0000000000..975907fa39
--- /dev/null
+++ b/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/MiscFuncs.c
@@ -0,0 +1,103 @@
+/** @file
+ Provide the misc functions to enable some CPU features.
+
+ Copyright (c) 1999 - 2015, 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 "CpuDxe.h"
+#include "PlatformMpService.h"
+#include "MiscFuncs.h"
+
+extern MP_SYSTEM_DATA *mMPSystemData;
+
+/**
+ @todo add description
+
+**/
+VOID
+EfiWriteToScript (
+ IN UINT32 Index,
+ IN UINT64 Value
+ )
+{
+ UINTN TableIndex;
+
+ if (mMPSystemData == NULL) {
+ ASSERT(mMPSystemData != NULL);
+ return;
+ }
+
+ //
+ // Save it into script
+ //
+ AsmAcquireMPLock (&(mMPSystemData->S3BootScriptLock));
+ TableIndex = mMPSystemData->S3BootScriptCount++;
+ AsmReleaseMPLock (&(mMPSystemData->S3BootScriptLock));
+
+ ASSERT (TableIndex < MAX_CPU_S3_TABLE_SIZE - 1);
+ mMPSystemData->S3BootScriptTable[TableIndex].ApicId = GetApicID (NULL, NULL);
+ mMPSystemData->S3BootScriptTable[TableIndex].MsrIndex = Index;
+ mMPSystemData->S3BootScriptTable[TableIndex].MsrValue = Value;
+}
+
+/**
+ @todo add description
+
+**/
+VOID
+EfiWriteMsrWithScript (
+ IN UINT32 Index,
+ IN UINT64 Value
+ )
+{
+ AsmWriteMsr64 (Index, Value);
+ EfiWriteToScript (Index, Value);
+}
+
+/**
+ Provide access to the CPU misc enables MSR
+
+ @param[in] Enable -Enable or Disable Misc Features
+
+**/
+VOID
+CpuMiscEnable (
+ BOOLEAN Enable,
+ UINT64 BitMask
+)
+{
+ UINT64 MsrValue;
+
+ MsrValue = AsmReadMsr64 (EFI_MSR_IA32_MISC_ENABLE);
+ if (Enable) {
+ MsrValue |= BitMask;
+ } else {
+ MsrValue &= ~BitMask;
+ }
+ AsmWriteMsr64 (EFI_MSR_IA32_MISC_ENABLE, MsrValue);
+}
+
+/**
+ @todo add description
+
+**/
+VOID
+ProgramProcessorFuncs (
+ IN MP_SYSTEM_DATA *MPSystemData
+ )
+{
+ //
+ // Initialize some misc functions
+ //
+ CpuMiscEnable (MPSystemData->MonitorMwaitEnable, B_EFI_MSR_IA32_MISC_ENABLE_MONITOR);
+
+}
diff --git a/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/MiscFuncs.h b/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/MiscFuncs.h
new file mode 100644
index 0000000000..c64c2d1dcc
--- /dev/null
+++ b/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/MiscFuncs.h
@@ -0,0 +1,45 @@
+/** @file
+ Provide the misc functions to enable some CPU features.
+
+ Copyright (c) 1999 - 2015, 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 _MISC_FUNCS_H_
+#define _MISC_FUNCS_H_
+
+#include "CpuDxe.h"
+#include "PlatformMpService.h"
+
+VOID
+EfiWriteToScript (
+ IN UINT32 Index,
+ IN UINT64 Value
+ );
+
+VOID
+EfiWriteMsrWithScript (
+ IN UINT32 Index,
+ IN UINT64 Value
+ );
+
+VOID
+ProgramProcessorFuncs (
+ IN MP_SYSTEM_DATA *MPSystemData
+ );
+
+VOID
+CpuMiscEnable (
+ BOOLEAN Enable,
+ UINT64 BitMask
+);
+
+#endif
diff --git a/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/MpCommon.c b/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/MpCommon.c
new file mode 100644
index 0000000000..ad98d91a56
--- /dev/null
+++ b/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/MpCommon.c
@@ -0,0 +1,879 @@
+/** @file
+ Code which support multi-processor.
+
+ Copyright (c) 1999 - 2015, 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 "MpCommon.h"
+#include "CpuDxe.h"
+#include "MiscFuncs.h"
+#include <Library/IoLib.h>
+#include <Protocol/SmmControl2.h>
+#include <Protocol/SmmAccess2.h>
+
+extern MP_SYSTEM_DATA *mMPSystemData;
+extern EFI_PHYSICAL_ADDRESS mOriginalBuffer;
+extern EFI_PHYSICAL_ADDRESS mBackupBuffer;
+extern EFI_METRONOME_ARCH_PROTOCOL *mMetronome;
+volatile UINTN mSwitchToLegacyRegionCount = 0;
+
+EFI_GUID mSmramCpuNvsHeaderGuid = EFI_SMRAM_CPU_NVS_HEADER_GUID;
+CHAR16 EfiPlatformCpuInfoVariable[] = L"PlatformCpuInfo";
+
+/**
+ @todo add description
+
+**/
+BOOLEAN
+IsXapicEnabled (
+ VOID
+ )
+{
+ UINT64 MsrValue;
+
+ MsrValue = AsmReadMsr64 (EFI_MSR_IA32_APIC_BASE);
+ if (MsrValue & B_EFI_MSR_IA32_APIC_BASE_APIC_GLOBAL_ENABLE) {
+ if (MsrValue & B_EFI_MSR_IA32_APIC_BASE_M_XAPIC) {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/**
+ @todo Add function description
+
+ @param[in] @todo add argument description
+
+ @retval @todo add return values
+
+**/
+UINT64
+ReadApicMsrOrMemory (
+ BOOLEAN XapicEnabled,
+ UINT32 MsrIndex,
+ UINT64 MemoryMappedIo
+)
+{
+ UINT64 Value;
+
+ if (XapicEnabled) {
+ Value = AsmReadMsr64 (MsrIndex);
+ } else {
+ Value = (UINT64)*(volatile UINT32 *)(UINTN)MemoryMappedIo;
+ }
+
+ return Value;
+}
+
+/**
+ @todo Add function description
+
+ @param[in] BSP - @todo add argument description
+
+ @retval @todo add return values
+
+**/
+VOID
+WriteApicMsrOrMemory (
+ BOOLEAN XapicEnabled,
+ UINT32 MsrIndex,
+ UINT64 MemoryMappedIo,
+ UINT64 Value
+)
+{
+ if (XapicEnabled) {
+ AsmWriteMsr64 (MsrIndex, Value);
+ } else {
+ if (MsrIndex == EFI_MSR_EXT_XAPIC_ICR) {
+ *(volatile UINT32 *)(UINTN)(MemoryMappedIo - APIC_REGISTER_ICR_LOW_OFFSET + APIC_REGISTER_ICR_HIGH_OFFSET) = (UINT32)(Value >> 32);
+ }
+ *(volatile UINT32 *)(UINTN)MemoryMappedIo = (UINT32)Value;
+ }
+}
+
+/**
+ @todo Add function description
+
+ @param[in] BroadcastMode - @todo add argument description
+ @param[in] ApicID - @todo add argument description
+ @param[in] VectorNumber - @todo add argument description
+ @param[in] DeliveryMode - @todo add argument description
+ @param[in] TriggerMode - @todo add argument description
+ @param[in] Assert - @todo add argument description
+
+ @retval EFI_INVALID_PARAMETER - @todo Add description for return value
+ @retval EFI_NOT_READY - @todo Add description for return value
+ @retval EFI_SUCCESS - @todo Add description for return value
+
+**/
+EFI_STATUS
+SendInterrupt (
+ IN UINT32 BroadcastMode,
+ IN UINT32 ApicID,
+ IN UINT32 VectorNumber,
+ IN UINT32 DeliveryMode,
+ IN UINT32 TriggerMode,
+ IN BOOLEAN Assert
+ )
+{
+ UINT64 ApicBaseReg;
+ EFI_PHYSICAL_ADDRESS ApicBase;
+ UINT32 ICRLow;
+ UINT32 ICRHigh;
+ BOOLEAN XapicEnabled;
+
+ if (SINGLE_THREAD_BOOT_FLAG != 0) {
+ //
+ // Only for Debug to use Single Thread Boot
+ //
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Initialze ICR high dword, since P6 family processor needs
+ // the destination field to be 0x0F when it is a broadcast
+ //
+ ICRHigh = 0x0f000000;
+ ICRLow = VectorNumber | (DeliveryMode << 8);
+
+ if (TriggerMode == TRIGGER_MODE_LEVEL) {
+ ICRLow |= 0x8000;
+ }
+
+ if (Assert) {
+ ICRLow |= 0x4000;
+ }
+
+ XapicEnabled = IsXapicEnabled ();
+
+ switch (BroadcastMode) {
+ case BROADCAST_MODE_SPECIFY_CPU:
+ if (XapicEnabled) {
+ ICRHigh = (UINT32)ApicID;
+ } else {
+ ICRHigh = ApicID << 24;
+ }
+ break;
+
+ case BROADCAST_MODE_ALL_INCLUDING_SELF:
+ ICRLow |= 0x80000;
+ break;
+
+ case BROADCAST_MODE_ALL_EXCLUDING_SELF:
+ ICRLow |= 0xC0000;
+ break;
+
+ default:
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ApicBaseReg = AsmReadMsr64 (EFI_MSR_IA32_APIC_BASE);
+ ApicBase = ApicBaseReg & B_EFI_MSR_IA32_APIC_BASE_APIC_BASE_ADDRESS;
+
+ //
+ // According Nehalem BWG, if Extended XAPIC Mode is enabled,
+ // legacy xAPIC is no longer working.
+ // So, previous MMIO offset must be transferred to MSR offset R/W.
+ // ----------------------------------------------------------------
+ // MMIO Offset MSR Offset Register Name
+ // ----------------------------------------------------------------
+ // 300h-310h 830h Interrupt Command Register [63:0]
+ // 831h [Reserved]
+ // ----------------------------------------------------------------
+ //
+ WriteApicMsrOrMemory (XapicEnabled, EFI_MSR_EXT_XAPIC_ICR, ApicBase + APIC_REGISTER_ICR_LOW_OFFSET, (((UINT64)ICRHigh << 32) | (UINT64)ICRLow));
+
+ gBS->Stall (10);
+
+ ICRLow = (UINT32)ReadApicMsrOrMemory (XapicEnabled, EFI_MSR_EXT_XAPIC_ICR, ApicBase + APIC_REGISTER_ICR_LOW_OFFSET);
+
+ if (ICRLow & 0x1000) {
+ return EFI_NOT_READY;
+ }
+
+ gBS->Stall (100);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ @todo Add function description
+
+ @param[out] *ApicBase OPTIONAL - @todo add argument description
+ @param[out] *ApicVersion OPTIONAL - @todo add argument description
+
+ @retval - @todo add return values
+
+**/
+UINT32
+GetApicID (
+ OUT EFI_PHYSICAL_ADDRESS *ApicBase OPTIONAL,
+ OUT UINT32 *ApicVersion OPTIONAL
+ )
+{
+ UINT64 ApicBaseReg;
+ UINT32 ApicID;
+ UINT32 LocalApicVersion;
+ UINT64 LocalApicBase;
+ UINTN MsrValue;
+ BOOLEAN XapicEnabled;
+
+ XapicEnabled = IsXapicEnabled ();
+
+ if (XapicEnabled) {
+ //
+ // According to Nehalem BWG, if Extended XAPIC Mode
+ // is enabled, legacy xAPIC is no longer working.
+ // So, previous MMIO offset must be transfered
+ // to MSR offset R/W.
+ // MMIO Offset MSR Offset Register Name
+ // 020h 802h EFI_EXT_XAPIC_LOGICAL_APIC_ID
+ // 030h 803h EFI_EXT_XAPIC_VERSION
+ //
+ MsrValue = (UINTN) AsmReadMsr64 (EFI_MSR_EXT_XAPIC_VERSION);
+ *ApicVersion = (UINT32) (MsrValue & B_EFI_MSR_EXT_XAPIC_VERSION_VERSION);
+ *ApicBase = 0;
+
+ MsrValue = (UINTN) AsmReadMsr64 (EFI_MSR_EXT_XAPIC_LOGICAL_APIC_ID);
+ ApicID = (UINT32) MsrValue;
+ return (ApicID);
+ }
+
+ ApicBaseReg = AsmReadMsr64 (EFI_MSR_IA32_APIC_BASE);
+ LocalApicBase = ApicBaseReg & B_EFI_MSR_IA32_APIC_BASE_APIC_BASE_ADDRESS;
+ if (ApicBase) {
+ *ApicBase = LocalApicBase;
+ }
+ //
+ // if Apic is not enabled yet, enable it here
+ //
+ if ((ApicBaseReg & B_EFI_MSR_IA32_APIC_BASE_APIC_GLOBAL_ENABLE) == 0) {
+ ApicBaseReg |= B_EFI_MSR_IA32_APIC_BASE_APIC_GLOBAL_ENABLE;
+ AsmWriteMsr64 (EFI_MSR_IA32_APIC_BASE, ApicBaseReg);
+ }
+
+ if (ApicVersion) {
+ LocalApicVersion = *(volatile UINT32 *) (UINTN) (LocalApicBase + APIC_REGISTER_APIC_VERSION_OFFSET);
+ *ApicVersion = LocalApicVersion & B_APIC_REGISTER_APIC_VERSION_OFFSET_VERSION_MASK;
+ }
+
+ ApicID = *(volatile UINT32 *) (UINTN) (LocalApicBase + APIC_REGISTER_LOCAL_ID_OFFSET);
+ return ((ApicID & B_APIC_REGISTER_LOCAL_ID_OFFSET_XAPIC_ID_MASK) >> N_APIC_REGISTER_LOCAL_ID_OFFSET_XAPIC_ID_MASK);
+}
+
+/**
+ @todo Add function description
+
+ @param[in] BSP - @todo add argument description
+
+ @retval - @todo add return values
+
+**/
+VOID
+ProgramVirtualWireMode (
+ BOOLEAN BSP
+ )
+{
+ UINT64 ApicBaseReg;
+ EFI_PHYSICAL_ADDRESS ApicBase;
+ UINT64 EntryValue;
+ BOOLEAN XapicEnabled;
+ UINT32 VirtualWire;
+
+ VirtualWire = 0;
+
+ ApicBaseReg = AsmReadMsr64 (EFI_MSR_IA32_APIC_BASE);
+ ApicBase = ApicBaseReg & B_EFI_MSR_IA32_APIC_BASE_APIC_BASE_ADDRESS;
+
+ XapicEnabled = IsXapicEnabled ();
+
+ //
+ // Program the Spurious Vector entry if XAPIC is enabled
+ //
+ EntryValue = ReadApicMsrOrMemory (XapicEnabled, EFI_MSR_EXT_XAPIC_SVR, ApicBase + APIC_REGISTER_SPURIOUS_VECTOR_OFFSET);
+ EntryValue &= 0xFFFFFD0F;
+ EntryValue |= 0x10F;
+ WriteApicMsrOrMemory (XapicEnabled, EFI_MSR_EXT_XAPIC_SVR, ApicBase + APIC_REGISTER_SPURIOUS_VECTOR_OFFSET, EntryValue);
+
+ //
+ // Double check if it is BSP
+ //
+ if (!BSP) {
+ CpuDisableInterrupt ();
+ }
+
+ //
+ // Program the LINT0 vector entry as EntInt
+ //
+ EntryValue = ReadApicMsrOrMemory (XapicEnabled, EFI_MSR_EXT_XAPIC_LVT_LINT0, ApicBase + APIC_REGISTER_LINT0_VECTOR_OFFSET);
+ if ((VirtualWire == VIRT_WIRE_A) && BSP) {
+ EntryValue &= 0xFFFE00FF;
+ EntryValue |= 0x700;
+ } else {
+ EntryValue |= 0x10000; // set bit 16 as mask for LINT0
+ }
+ WriteApicMsrOrMemory (XapicEnabled, EFI_MSR_EXT_XAPIC_LVT_LINT0, ApicBase + APIC_REGISTER_LINT0_VECTOR_OFFSET, EntryValue);
+
+ if ((VirtualWire != VIRT_WIRE_A) && BSP) {
+ //
+ // Initialize the IOXApic RT table
+ //
+ *(volatile UINT8 *)(UINTN)IO_APIC_INDEX_REGISTER = 0x10;
+ *(volatile UINT32 *)(UINTN)IO_APIC_DATA_REGISTER = 0x0700;
+ *(volatile UINT8 *)(UINTN)IO_APIC_INDEX_REGISTER = 0x11;
+ *(volatile UINT32 *)(UINTN)IO_APIC_DATA_REGISTER = (GetApicID (NULL, NULL) << 24);
+ }
+}
+
+/**
+ @todo Add function description
+
+ @param[out] WakeUpBuffer - @todo add argument description
+
+ @retval - @todo add return values
+
+**/
+EFI_STATUS
+AllocateWakeUpBuffer (
+ OUT EFI_PHYSICAL_ADDRESS *WakeUpBuffer
+ )
+{
+ EFI_STATUS Status;
+
+ Status = EFI_SUCCESS;
+ for (*WakeUpBuffer = 0x8F000; *WakeUpBuffer >= 0x2000; *WakeUpBuffer -= 0x1000) {
+ Status = gBS->AllocatePages (
+ AllocateAddress,
+ EfiACPIMemoryNVS,
+ 1,
+ WakeUpBuffer
+ );
+
+ if (!EFI_ERROR (Status)) {
+ break;
+ }
+ }
+
+ return Status;
+}
+
+/**
+ @todo Add function description
+
+ @param[in] Size - @todo add argument description
+ @param[in] Alignment - @todo add argument description
+ @param[out] **Pointer - @todo add argument description
+
+ @retval EFI_SUCCESS - @todo Add description for return value
+
+**/
+EFI_STATUS
+AllocateAlignedReservedMemory (
+ IN UINTN Size,
+ IN UINTN Alignment,
+ OUT VOID **Pointer
+ )
+{
+ EFI_STATUS Status;
+ UINTN PointerValue;
+
+ Status = AllocateReservedMemoryBelow4G (
+ Size + Alignment - 1,
+ (VOID **) Pointer
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ PointerValue = (UINTN) *Pointer;
+ PointerValue = (PointerValue + Alignment - 1) / Alignment * Alignment;
+
+ *Pointer = (VOID *) PointerValue;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Allocate EfiACPIMemoryNVS below 4G memory address.
+
+ @param[in] Size Size of memory to allocate.
+ @param[out] Buffer Allocated address for output.
+
+ @retval EFI_SUCCESS Memory successfully allocated.
+ @retval Other Other errors occur.
+
+**/
+EFI_STATUS
+AllocateReservedMemoryBelow4G (
+ IN UINTN Size,
+ OUT VOID **Buffer
+ )
+{
+ UINTN Pages;
+ EFI_PHYSICAL_ADDRESS Address;
+ EFI_STATUS Status;
+
+ Pages = EFI_SIZE_TO_PAGES (Size);
+ Address = 0xffffffff;
+
+ Status = gBS->AllocatePages (
+ AllocateMaxAddress,
+ EfiACPIMemoryNVS,
+ Pages,
+ &Address
+ );
+
+ *Buffer = (VOID *) (UINTN) Address;
+
+ return Status;
+}
+
+#ifdef __GNUC__
+#define _ReadWriteBarrier() do { __asm__ __volatile__ ("": : : "memory"); } while(0)
+
+int _outp(
+ unsigned short port,
+ int databyte
+ )
+{
+ __asm__ __volatile__ ("outb %b0,%w1" : : "a" (databyte), "d" ((UINT16)port));
+ return databyte;
+}
+#else
+#pragma intrinsic(_outp, _ReadWriteBarrier)
+#endif
+
+/**
+ @todo add description
+
+**/
+VOID
+EFIAPI
+CpuIoWrite8 (
+ IN UINT16 Port,
+ IN UINT32 Data
+ )
+{
+ _ReadWriteBarrier();
+ _outp (Port, (int)Data);
+}
+
+/**
+ This function is invoked when SMM_BASE protocol is installed, then we
+ allocate SMRAM and save all information there.
+
+ @param[in] Event The triggered event.
+ @param[in] Context Context for this event.
+
+**/
+VOID
+EFIAPI
+InitSmramDataContent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_SMM_ACCESS2_PROTOCOL *SmmAccess;
+ EFI_SMRAM_DESCRIPTOR *SmramRanges;
+ UINTN Size;
+ SMRAM_CPU_DATA SmramCpuDataTemplate;
+ UINTN LockBoxSize;
+ IA32_DESCRIPTOR *Idtr;
+ IA32_DESCRIPTOR *Gdtr;
+ UINTN MicrocodeSize;
+ EFI_CPU_MICROCODE_HEADER **Microcode;
+ UINT8 *LockBoxMicrocode;
+ UINTN Index;
+ EFI_STATUS Status;
+ EFI_SMM_CONTROL2_PROTOCOL *SmmControl;
+ UINT8 *SmramCpuData;
+ UINTN VarSize;
+ UINT64 VarData[3];
+ UINTN ArgBufferSize;
+ UINT8 ArgBuffer;
+
+ DEBUG ((EFI_D_ERROR, "InitSmramDataContent\n"));
+ Status = gBS->LocateProtocol(&gEfiSmmAccess2ProtocolGuid, NULL, (VOID **) &SmmAccess);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = gBS->LocateProtocol(&gEfiSmmControl2ProtocolGuid, NULL, (VOID **) &SmmControl);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Get SMRAM information
+ //
+ Size = 0;
+ Status = SmmAccess->GetCapabilities (SmmAccess, &Size, NULL);
+ ASSERT (Status == EFI_BUFFER_TOO_SMALL);
+
+ Status = gBS->AllocatePool (
+ EfiBootServicesData,
+ Size,
+ (VOID **)&SmramRanges
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = SmmAccess->GetCapabilities (
+ SmmAccess,
+ &Size,
+ SmramRanges
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Open all SMRAM ranges
+ //
+ Size /= sizeof (*SmramRanges);
+ Status = SmmAccess->Open (SmmAccess);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Init
+ //
+ CopyMem (&SmramCpuDataTemplate.HeaderGuid, &mSmramCpuNvsHeaderGuid, sizeof(EFI_GUID));
+ SmramCpuDataTemplate.AcpiCpuPointer = (EFI_PHYSICAL_ADDRESS)(UINTN)mAcpiCpuData;
+ CopyMem (&SmramCpuDataTemplate.AcpiCpuData, mAcpiCpuData, sizeof(ACPI_CPU_DATA_COMPATIBILITY));
+
+ //
+ // Calculate size
+ //
+ SmramCpuDataTemplate.GdtrProfileSize = sizeof (IA32_DESCRIPTOR);
+ Gdtr = (IA32_DESCRIPTOR *)(UINTN)mAcpiCpuData->GdtrProfile;
+ SmramCpuDataTemplate.GdtSize = Gdtr->Limit + 1;
+ SmramCpuDataTemplate.IdtrProfileSize = sizeof (IA32_DESCRIPTOR);
+ Idtr = (IA32_DESCRIPTOR *)(UINTN)mAcpiCpuData->GdtrProfile;
+ SmramCpuDataTemplate.IdtSize = Idtr->Limit + 1;
+ SmramCpuDataTemplate.CpuPrivateDataSize = sizeof(MP_CPU_S3_DATA_POINTER);
+ SmramCpuDataTemplate.S3BootScriptTableSize = sizeof(mMPSystemData->S3BootScriptTable);
+ SmramCpuDataTemplate.S3BspMtrrTableSize = sizeof(mMPSystemData->S3BspMtrrTable);
+ //
+ // Record best match for each CPU Microcode and NULL for end
+ //
+ SmramCpuDataTemplate.MicrocodePointerBufferSize = sizeof(UINT32) * (mAcpiCpuData->NumberOfCpus + 1);
+ //
+ // Calculate Microcode DataSize
+ //
+ SmramCpuDataTemplate.MicrocodeDataBufferSize = 0;
+ Microcode = (VOID *)(UINTN)mAcpiCpuData->MicrocodePointerBuffer;
+ if (Microcode != NULL) {
+ Index = 0;
+ MicrocodeSize = 0;
+ while (Microcode[Index] != NULL) {
+ if (Microcode[Index]->DataSize == 0) {
+ MicrocodeSize = 2048;
+ } else {
+ MicrocodeSize = Microcode[Index]->TotalSize;
+ }
+ SmramCpuDataTemplate.MicrocodeDataBufferSize += (UINT32)MicrocodeSize;
+ Index ++;
+ }
+ }
+
+ SmramCpuDataTemplate.GdtrProfileOffset = sizeof(SMRAM_CPU_DATA);
+ SmramCpuDataTemplate.GdtOffset = SmramCpuDataTemplate.GdtrProfileOffset +
+ SmramCpuDataTemplate.GdtrProfileSize;
+ SmramCpuDataTemplate.IdtrProfileOffset = SmramCpuDataTemplate.GdtOffset +
+ SmramCpuDataTemplate.GdtSize;
+ SmramCpuDataTemplate.IdtOffset = SmramCpuDataTemplate.IdtrProfileOffset +
+ SmramCpuDataTemplate.IdtrProfileSize;
+ SmramCpuDataTemplate.CpuPrivateDataOffset = SmramCpuDataTemplate.IdtOffset +
+ SmramCpuDataTemplate.IdtSize;
+ SmramCpuDataTemplate.S3BootScriptTableOffset = SmramCpuDataTemplate.CpuPrivateDataOffset +
+ SmramCpuDataTemplate.CpuPrivateDataSize;
+ SmramCpuDataTemplate.S3BspMtrrTableOffset = SmramCpuDataTemplate.S3BootScriptTableOffset +
+ SmramCpuDataTemplate.S3BootScriptTableSize;
+ SmramCpuDataTemplate.MicrocodePointerBufferOffset = SmramCpuDataTemplate.S3BspMtrrTableOffset +
+ SmramCpuDataTemplate.S3BspMtrrTableSize;
+ SmramCpuDataTemplate.MicrocodeDataBufferOffset = SmramCpuDataTemplate.MicrocodePointerBufferOffset +
+ SmramCpuDataTemplate.MicrocodePointerBufferSize;
+
+ LockBoxSize = sizeof(SMRAM_CPU_DATA) +
+ SmramCpuDataTemplate.GdtrProfileSize +
+ SmramCpuDataTemplate.GdtSize +
+ SmramCpuDataTemplate.IdtrProfileSize +
+ SmramCpuDataTemplate.IdtSize +
+ SmramCpuDataTemplate.CpuPrivateDataSize +
+ SmramCpuDataTemplate.S3BootScriptTableSize +
+ SmramCpuDataTemplate.S3BspMtrrTableSize +
+ SmramCpuDataTemplate.MicrocodePointerBufferSize +
+ SmramCpuDataTemplate.MicrocodeDataBufferSize;
+
+ DEBUG ((EFI_D_ERROR, "LockBoxSize - %x\n", LockBoxSize));
+ DEBUG ((EFI_D_ERROR, "SmramCpuData.GdtrProfileSize - %x\n", SmramCpuDataTemplate.GdtrProfileSize));
+ DEBUG ((EFI_D_ERROR, "SmramCpuData.GdtSize - %x\n", SmramCpuDataTemplate.GdtSize));
+ DEBUG ((EFI_D_ERROR, "SmramCpuData.IdtrProfileSize - %x\n", SmramCpuDataTemplate.IdtrProfileSize));
+ DEBUG ((EFI_D_ERROR, "SmramCpuData.IdtSize - %x\n", SmramCpuDataTemplate.IdtSize));
+ DEBUG ((EFI_D_ERROR, "SmramCpuData.CpuPrivateDataSize - %x\n", SmramCpuDataTemplate.CpuPrivateDataSize));
+ DEBUG ((EFI_D_ERROR, "SmramCpuData.S3BootScriptTableSize - %x\n", SmramCpuDataTemplate.S3BootScriptTableSize));
+ DEBUG ((EFI_D_ERROR, "SmramCpuData.S3BspMtrrTableSize - %x\n", SmramCpuDataTemplate.S3BspMtrrTableSize));
+ DEBUG ((EFI_D_ERROR, "SmramCpuData.MicrocodePointerBufferSize - %x\n", SmramCpuDataTemplate.MicrocodePointerBufferSize));
+ DEBUG ((EFI_D_ERROR, "SmramCpuData.MicrocodeDataBufferSize - %x\n", SmramCpuDataTemplate.MicrocodeDataBufferSize));
+
+ DEBUG ((EFI_D_ERROR, "SmramCpuData.GdtrProfileOffset - %x\n", SmramCpuDataTemplate.GdtrProfileOffset));
+ DEBUG ((EFI_D_ERROR, "SmramCpuData.GdtOffset - %x\n", SmramCpuDataTemplate.GdtOffset));
+ DEBUG ((EFI_D_ERROR, "SmramCpuData.IdtrProfileOffset - %x\n", SmramCpuDataTemplate.IdtrProfileOffset));
+ DEBUG ((EFI_D_ERROR, "SmramCpuData.IdtOffset - %x\n", SmramCpuDataTemplate.IdtOffset));
+ DEBUG ((EFI_D_ERROR, "SmramCpuData.CpuPrivateDataOffset - %x\n", SmramCpuDataTemplate.CpuPrivateDataOffset));
+ DEBUG ((EFI_D_ERROR, "SmramCpuData.S3BootScriptTableOffset - %x\n", SmramCpuDataTemplate.S3BootScriptTableOffset));
+ DEBUG ((EFI_D_ERROR, "SmramCpuData.S3BspMtrrTableOffset - %x\n", SmramCpuDataTemplate.S3BspMtrrTableOffset));
+ DEBUG ((EFI_D_ERROR, "SmramCpuData.MicrocodePointerBufferOffset - %x\n", SmramCpuDataTemplate.MicrocodePointerBufferOffset));
+ DEBUG ((EFI_D_ERROR, "SmramCpuData.MicrocodeDataBufferOffset - %x\n", SmramCpuDataTemplate.MicrocodeDataBufferOffset));
+
+ //
+ // Allocate Normal Memory
+ //
+ Status = gBS->AllocatePool (
+ EfiBootServicesData,
+ LockBoxSize,
+ (VOID **)&SmramCpuData
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Allocate SMRAM
+ //
+ //
+ // Copy data buffer
+ //
+ CopyMem (SmramCpuData, &SmramCpuDataTemplate, sizeof(SmramCpuDataTemplate));
+
+ CopyMem (
+ SmramCpuData + SmramCpuDataTemplate.GdtrProfileOffset,
+ (VOID *)(UINTN)mAcpiCpuData->GdtrProfile,
+ SmramCpuDataTemplate.GdtrProfileSize
+ );
+ CopyMem (
+ SmramCpuData + SmramCpuDataTemplate.GdtOffset,
+ (VOID *)(UINTN)Gdtr->Base,
+ SmramCpuDataTemplate.GdtSize
+ );
+ CopyMem (
+ SmramCpuData + SmramCpuDataTemplate.IdtrProfileOffset,
+ (VOID *)(UINTN)mAcpiCpuData->IdtrProfile,
+ SmramCpuDataTemplate.IdtrProfileSize
+ );
+ CopyMem (
+ SmramCpuData + SmramCpuDataTemplate.IdtOffset,
+ (VOID *)(UINTN)Idtr->Base,
+ SmramCpuDataTemplate.IdtSize
+ );
+ CopyMem (
+ SmramCpuData + SmramCpuDataTemplate.CpuPrivateDataOffset,
+ (VOID *)(UINTN)mAcpiCpuData->CpuPrivateData,
+ SmramCpuDataTemplate.CpuPrivateDataSize
+ );
+ CopyMem (
+ SmramCpuData + SmramCpuDataTemplate.S3BootScriptTableOffset,
+ (VOID *)(UINTN)mMPSystemData->S3DataPointer.S3BootScriptTable,
+ SmramCpuDataTemplate.S3BootScriptTableSize
+ );
+ CopyMem (
+ SmramCpuData + SmramCpuDataTemplate.S3BspMtrrTableOffset,
+ (VOID *)(UINTN)mMPSystemData->S3DataPointer.S3BspMtrrTable,
+ SmramCpuDataTemplate.S3BspMtrrTableSize
+ );
+ CopyMem (
+ SmramCpuData + SmramCpuDataTemplate.MicrocodePointerBufferOffset,
+ (VOID *)(UINTN)mAcpiCpuData->MicrocodePointerBuffer,
+ SmramCpuDataTemplate.MicrocodePointerBufferSize
+ );
+ //
+ // Copy Microcode
+ //
+ LockBoxMicrocode = SmramCpuData + SmramCpuDataTemplate.MicrocodeDataBufferOffset;
+ Microcode = (VOID *)(UINTN)mAcpiCpuData->MicrocodePointerBuffer;
+ if (Microcode != NULL) {
+ Index = 0;
+ MicrocodeSize = 0;
+ while (Microcode[Index] != NULL) {
+ if (Microcode[Index]->DataSize == 0) {
+ MicrocodeSize = 2048;
+ } else {
+ MicrocodeSize = Microcode[Index]->TotalSize;
+ }
+ CopyMem (LockBoxMicrocode, Microcode[Index], MicrocodeSize);
+ LockBoxMicrocode += MicrocodeSize;
+ Index ++;
+ }
+ }
+
+ //
+ // Copy to SMRAM
+ //
+ //
+ // We have to use SMI to copy SMRAM, because we can not access SMRAM after SMRR enabled.
+ // SMM_ACCESS.Open () takes no effect.
+ //
+ VarSize = sizeof(VarData);
+ VarData[0] = 0;
+ VarData[1] = (UINT64)(UINTN)SmramCpuData;
+ VarData[2] = (UINT64)LockBoxSize;
+ Status = gRT->SetVariable (
+ L"SmramCpuNvs",
+ &mSmramCpuNvsHeaderGuid,
+ EFI_VARIABLE_BOOTSERVICE_ACCESS,
+ VarSize,
+ VarData
+ );
+ ASSERT_EFI_ERROR (Status);
+ ///
+ /// Fill SMI data port
+ ///
+ IoWrite8 (0xB3, 0x81);
+
+ //
+ // Trigger SMI
+ //
+ ArgBufferSize = sizeof (ArgBuffer);
+ ArgBuffer = 0x55;
+ Status = SmmControl->Trigger (SmmControl, (UINT8 *)&ArgBuffer, (UINT8 *)&ArgBufferSize, FALSE, 0);
+ Status = SmmControl->Clear (SmmControl, 0);
+
+ //
+ // Close all SMRAM ranges
+ //
+ Status = SmmAccess->Close (SmmAccess);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Free resource
+ //
+ gBS->FreePool (SmramRanges);
+
+ //
+ // Done
+ //
+ return ;
+}
+
+/**
+ This function is invoked when LegacyBios protocol is installed, we must
+ allocate reserved memory under 1M for AP.
+
+ @param[in] Event The triggered event.
+ @param[in] Context Context for this event.
+
+ @retval None
+
+**/
+VOID
+EFIAPI
+ReAllocateMemoryForAP (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_PHYSICAL_ADDRESS LegacyRegion;
+ EFI_STATUS Status;
+ MP_CPU_EXCHANGE_INFO *ExchangeInfo;
+
+ STATIC BOOLEAN InitDone = FALSE;
+ if (InitDone) {
+ return ;
+ }
+ InitDone = TRUE;
+
+ while (ApRunning()) {
+ CpuPause ();
+ }
+
+ {
+ //
+ // The BackBuffer is 4k.
+ // Allocate 0x2000 bytes from below 640K memory to make sure I can
+ // get a 4k aligned spaces of 0x1000 bytes, since Alignment argument does not work.
+ //
+ LegacyRegion = 0x9FFFF;
+ Status = gBS->AllocatePages (
+ AllocateMaxAddress,
+ EfiReservedMemoryType,
+ EFI_SIZE_TO_PAGES (0x2000),
+ &LegacyRegion
+ );
+ ASSERT_EFI_ERROR (Status);
+ DEBUG ((EFI_D_ERROR, "LegacyRegion NonCSM - %x\n", LegacyRegion));
+ if (EFI_ERROR (Status)) {
+ return ;
+ }
+ }
+
+ DEBUG((EFI_D_INFO, "LegacyRegion: 0x%08x\r\n", (UINT32)(UINTN)LegacyRegion));
+ //
+ // This address should be less than A seg.
+ // And it should be aligned to 4K
+ //
+ ASSERT (!((UINTN)LegacyRegion & 0x0FFF) && ((UINTN)LegacyRegion < 0xA0000));
+
+ mAcpiCpuData->WakeUpBuffer = (EFI_PHYSICAL_ADDRESS) LegacyRegion;
+ mAcpiCpuData->WakeUpBuffer = (mAcpiCpuData->WakeUpBuffer + 0x0fff) & 0x0fffff000;
+
+ ExchangeInfo = (MP_CPU_EXCHANGE_INFO *) (UINTN) (mBackupBuffer + MP_CPU_EXCHANGE_INFO_OFFSET);
+ ExchangeInfo->BufferStart = (UINT32) mAcpiCpuData->WakeUpBuffer;
+ ExchangeInfo->ApFunction = (VOID *) (UINTN) LegacyRegionAPCount;
+
+ gBS->CopyMem (
+ (VOID *) (UINTN) mAcpiCpuData->WakeUpBuffer,
+ (VOID *) (UINTN) mBackupBuffer,
+ EFI_PAGE_SIZE
+ );
+ RedirectFarJump();
+
+ //
+ // Do final intialization for APs
+ // Is it neccessary?
+ //
+ SendInterrupt (BROADCAST_MODE_ALL_EXCLUDING_SELF, 0, 0, DELIVERY_MODE_INIT, TRIGGER_MODE_EDGE, TRUE);
+ SendInterrupt (
+ BROADCAST_MODE_ALL_EXCLUDING_SELF,
+ 0,
+ (UINT32) RShiftU64 (mAcpiCpuData->WakeUpBuffer, 12),
+ DELIVERY_MODE_SIPI,
+ TRIGGER_MODE_EDGE,
+ TRUE
+ );
+ //
+ // Wait until all APs finish
+ //
+ while (mSwitchToLegacyRegionCount < mAcpiCpuData->NumberOfCpus - 1) {
+ CpuPause ();
+ }
+
+ ExchangeInfo->ApFunction = (VOID *) (UINTN) ApProcWrapper;
+ gBS->CopyMem (
+ (VOID *) (UINTN) mAcpiCpuData->WakeUpBuffer,
+ (VOID *) (UINTN) mBackupBuffer,
+ EFI_PAGE_SIZE
+ );
+ RedirectFarJump();
+
+ InitSmramDataContent (NULL, NULL);
+}
+
+/**
+ This function is invoked by EFI_EVENT_SIGNAL_LEGACY_BOOT.
+ Before booting to legacy OS, reset AP's wakeup buffer address,
+ preparing for S3 usage.
+
+ @param[in] Event The triggered event.
+ @param[in] Context Context for this event.
+
+ @retval None
+
+**/
+VOID
+ResetAPs (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+}
diff --git a/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/MpCommon.h b/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/MpCommon.h
new file mode 100644
index 0000000000..33840aa76e
--- /dev/null
+++ b/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/MpCommon.h
@@ -0,0 +1,425 @@
+/** @file
+ Some definitions for MP and HT driver.
+
+ Copyright (c) 1999 - 2015, 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 _MP_COMMON_
+#define _MP_COMMON_
+
+#include "CpuDxe.h"
+#include "Exception.h"
+#include "ProcessorDef.h"
+
+#define EFI_CPU_CAUSE_NOT_DISABLED 0x0000
+#define EFI_CPU_CAUSE_INTERNAL_ERROR 0x0001
+#define EFI_CPU_CAUSE_THERMAL_ERROR 0x0002
+#define EFI_CPU_CAUSE_SELFTEST_FAILURE 0x0004
+#define EFI_CPU_CAUSE_PREBOOT_TIMEOUT 0x0008
+#define EFI_CPU_CAUSE_FAILED_TO_START 0x0010
+#define EFI_CPU_CAUSE_CONFIG_ERROR 0x0020
+#define EFI_CPU_CAUSE_USER_SELECTION 0x0080
+#define EFI_CPU_CAUSE_BY_ASSOCIATION 0x0100
+#define EFI_CPU_CAUSE_UNSPECIFIED 0x8000
+
+#define VacantFlag 0x00
+#define NotVacantFlag 0xff
+
+#define MICROSECOND 10
+
+#define MAXIMUM_CPU_NUMBER 0x40
+#define STACK_SIZE_PER_PROC 0x8000
+
+#define IO_APIC_INDEX_REGISTER 0xFEC00000
+#define IO_APIC_DATA_REGISTER 0xFEC00010
+#define VIRT_WIRE_A 0
+
+//
+// Data structure used in MP/HT driver
+//
+#define MP_CPU_EXCHANGE_INFO_OFFSET (0x1000 - 0x400)
+#define MP_CPU_LEGACY_RESET_INFO_OFFSET (0x100 - 0x20)
+
+#pragma pack(1)
+#define SIZE_OF_MCE_HANDLER 16
+
+/**
+ @todo add description
+
+**/
+typedef struct {
+ UINT16 LimitLow;
+ UINT16 BaseLow;
+ UINT8 BaseMiddle;
+ UINT16 Attributes;
+ UINT8 BaseHigh;
+} SEGMENT_DESCRIPTOR;
+
+#pragma pack()
+
+/**
+ @todo add description
+
+**/
+typedef struct {
+ UINT32 Number;
+ UINT32 BIST;
+} BIST_INFO;
+
+typedef enum {
+ WakeUpApCounterInit = 0,
+ WakeUpApPerHltLoop = 1,
+ WakeUpApPerMwaitLoop= 2,
+ WakeUpApPerRunLoop = 3
+} WAKEUP_AP_MANNER;
+
+/**
+ @todo add description
+
+**/
+typedef struct {
+ UINTN Lock;
+ VOID *StackStart;
+ UINTN StackSize;
+ VOID *ApFunction;
+ IA32_DESCRIPTOR GdtrProfile;
+ IA32_DESCRIPTOR IdtrProfile;
+ UINT32 BufferStart;
+ UINT32 Cr3;
+ UINT32 InitFlag;
+ WAKEUP_AP_MANNER WakeUpApManner;
+ BIST_INFO BistBuffer[MAXIMUM_CPU_NUMBER];
+} MP_CPU_EXCHANGE_INFO;
+
+extern ACPI_CPU_DATA_COMPATIBILITY *mAcpiCpuData;
+
+//
+// Protocol interface functions
+//
+/**
+ Implementation of GetNumberOfProcessors() service of MP Services Protocol.
+
+ This service retrieves the number of logical processor in the platform
+ and the number of those logical processors that are enabled on this boot.
+ This service may only be called from the BSP.
+
+ @param[in] This A pointer to the EFI_MP_SERVICES_PROTOCOL instance.
+ @param[in] NumberOfProcessors Pointer to the total number of logical processors in the system,
+ including the BSP and disabled APs.
+ @param[in] NumberOfEnabledProcessors Pointer to the number of enabled logical processors that exist
+ in system, including the BSP.
+
+ @retval EFI_SUCCESS Number of logical processors and enabled logical processors retrieved..
+ @retval EFI_DEVICE_ERROR Caller processor is AP.
+ @retval EFI_INVALID_PARAMETER NumberOfProcessors is NULL.
+ @retval EFI_INVALID_PARAMETER NumberOfEnabledProcessors is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+GetNumberOfProcessors (
+ IN EFI_MP_SERVICES_PROTOCOL *This,
+ OUT UINTN *NumberOfProcessors,
+ OUT UINTN *NumberOfEnabledProcessors
+ );
+
+/**
+ Implementation of GetProcessorInfo() service of MP Services Protocol.
+
+ Gets detailed MP-related information on the requested processor at the
+ instant this call is made. This service may only be called from the BSP.
+
+ @param[in] This A pointer to the EFI_MP_SERVICES_PROTOCOL instance.
+ @param[in] ProcessorNumber The handle number of processor.
+ @param[in] ProcessorInfoBuffer A pointer to the buffer where information for the requested processor is deposited.
+
+ @retval EFI_SUCCESS Processor information successfully returned.
+ @retval EFI_DEVICE_ERROR Caller processor is AP.
+ @retval EFI_INVALID_PARAMETER ProcessorInfoBuffer is NULL
+ @retval EFI_NOT_FOUND Processor with the handle specified by ProcessorNumber does not exist.
+
+**/
+EFI_STATUS
+EFIAPI
+GetProcessorInfo (
+ IN EFI_MP_SERVICES_PROTOCOL *This,
+ IN UINTN ProcessorNumber,
+ OUT EFI_PROCESSOR_INFORMATION *ProcessorInfoBuffer
+ );
+
+/**
+ MP Service to get specified application processor (AP)
+ to execute a caller-provided code stream.
+
+ @param[in] This Pointer to MP Service Protocol
+ @param[in] Procedure The procedure to be assigned to AP.
+ @param[in] ProcessorNumber Cpu number
+ @param[in] WaitEvent If timeout, the event to be triggered after this AP finishes.
+ @param[in] TimeoutInMicroSecs The timeout value in microsecond. Zero means infinity.
+ @param[in] ProcArguments Argument for Procedure.
+
+ @retval EFI_INVALID_PARAMETER Procudure is NULL.
+ @retval EFI_INVALID_PARAMETER Number of CPU out of range, or it belongs to BSP.
+ @retval EFI_INVALID_PARAMETER Specified CPU is not idle.
+ @retval EFI_SUCCESS The AP has finished.
+ @retval EFI_TIMEOUT Time goes out before the AP has finished.
+
+**/
+EFI_STATUS
+EFIAPI
+StartupThisAP (
+ IN EFI_MP_SERVICES_PROTOCOL *This,
+ IN EFI_AP_PROCEDURE Procedure,
+ IN UINTN ProcessorNumber,
+ IN EFI_EVENT WaitEvent OPTIONAL,
+ IN UINTN TimeoutInMicroSecs OPTIONAL,
+ IN VOID *ProcArguments OPTIONAL,
+ OUT BOOLEAN *Finished OPTIONAL
+ );
+
+/**
+ MP Service to get all the available application processors (APs)
+ to execute a caller-provided code stream.
+
+ @param[in] This Pointer to MP Service Protocol
+ @param[in] Procedure The procedure to be assigned to APs.
+ @param[in] SingleThread If true, all APs execute in block mode.
+ Otherwise, all APs exceute in non-block mode.
+ @param[in] WaitEvent If timeout, the event to be triggered after all APs finish.
+ @param[in] TimeoutInMicroSecs The timeout value in microsecond. Zero means infinity.
+ @param[in] ProcArguments Argument for Procedure.
+ @param[in] FailedCPUList If not NULL, all APs that fail to start will be recorded in the list.
+
+ @retval EFI_INVALID_PARAMETER Procudure is NULL.
+ @retval EFI_SUCCESS Only 1 logical processor exists.
+ @retval EFI_SUCCESS All APs have finished.
+ @retval EFI_TIMEOUT Time goes out before all APs have finished.
+
+**/
+EFI_STATUS
+EFIAPI
+StartupAllAPs (
+ IN EFI_MP_SERVICES_PROTOCOL *This,
+ IN EFI_AP_PROCEDURE Procedure,
+ IN BOOLEAN SingleThread,
+ IN EFI_EVENT WaitEvent OPTIONAL,
+ IN UINTN TimeoutInMicroSecs,
+ IN VOID *ProcArguments OPTIONAL,
+ OUT UINTN **FailedCPUList OPTIONAL
+ );
+
+/**
+ MP Service to makes the current BSP into an AP and then switches the
+ designated AP into the AP. This procedure is usually called after a CPU
+ test that has found that BSP is not healthy to continue it's responsbilities.
+
+ @param[in] This Pointer to MP Service Protocol.
+ @param[in] ProcessorNumber The handle number of processor.
+ @param[in] OldBSPState Whether to enable or disable the original BSP.
+
+ @retval EFI_INVALID_PARAMETER Number for Specified AP out of range.
+ @retval EFI_INVALID_PARAMETER Number of specified CPU belongs to BSP.
+ @retval EFI_NOT_READY Specified AP is not idle.
+ @retval EFI_SUCCESS BSP successfully switched.
+
+**/
+EFI_STATUS
+EFIAPI
+SwitchBSP (
+ IN EFI_MP_SERVICES_PROTOCOL *This,
+ IN UINTN ProcessorNumber,
+ IN BOOLEAN OldBSPState
+ );
+
+/**
+ This procedure enables or disables APs.
+
+ @param[in] This Pointer to MP Service Protocol.
+ @param[in] ProcessorNumber The handle number of processor.
+ @param[in] NewAPState Indicate new desired AP state
+ @param[in] HealthState If not NULL, it points to the value that specifies the new health status of the AP.
+ If it is NULL, this parameter is ignored.
+
+ @retval EFI_INVALID_PARAMETER Input paramters were not correct.
+ @retval EFI_SUCCESS Function completed successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+EnableDisableAP (
+ IN EFI_MP_SERVICES_PROTOCOL *This,
+ IN UINTN ProcessorNumber,
+ IN BOOLEAN NewAPState,
+ IN UINT32 *HealthState OPTIONAL
+ );
+
+/**
+ Implementation of WhoAmI() service of MP Services Protocol.
+
+ This service lets the caller processor get its handle number.
+ This service may be called from the BSP and APs.
+
+ @param[in] This A pointer to the EFI_MP_SERVICES_PROTOCOL instance.
+ @param[in] ProcessorNumber Pointer to the handle number of AP.
+
+ @retval EFI_SUCCESS Processor number successfully returned.
+ @retval EFI_INVALID_PARAMETER ProcessorNumber is NULL
+
+**/
+EFI_STATUS
+EFIAPI
+WhoAmI (
+ IN EFI_MP_SERVICES_PROTOCOL *This,
+ OUT UINTN *CpuNumber
+ );
+
+//
+// Functions shared in MP/HT drivers
+//
+EFI_STATUS
+SendInterrupt (
+ IN UINT32 BroadcastMode,
+ IN UINT32 ApicID,
+ IN UINT32 VectorNumber,
+ IN UINT32 DeliveryMode,
+ IN UINT32 TriggerMode,
+ IN BOOLEAN Assert
+ );
+
+UINT32
+GetApicID (
+ OUT EFI_PHYSICAL_ADDRESS *ApicBase OPTIONAL,
+ OUT UINT32 *ApicVersionNumber OPTIONAL
+ );
+
+VOID
+ProgramVirtualWireMode (
+ IN BOOLEAN BSP
+ );
+
+EFI_STATUS
+AllocateWakeUpBuffer (
+ OUT EFI_PHYSICAL_ADDRESS *WakeUpBuffer
+ );
+
+//
+// Assembly functions implemented in MP/HT drivers
+//
+VOID
+AsmAcquireMPLock (
+ IN UINT8 *Lock
+ );
+
+VOID
+AsmReleaseMPLock (
+ IN UINT8 *Lock
+ );
+
+VOID
+AsmGetGdtrIdtr (
+ OUT IA32_DESCRIPTOR **Gdt,
+ OUT IA32_DESCRIPTOR **Idt
+ );
+
+EFI_STATUS
+PrepareGdtIdtForAP (
+ OUT IA32_DESCRIPTOR *GDTR,
+ OUT IA32_DESCRIPTOR *IDTR
+ );
+
+EFI_STATUS
+AllocateAlignedReservedMemory (
+ IN UINTN Size,
+ IN UINTN Alignment,
+ OUT VOID **Pointer
+ );
+
+UINT64
+AsmGetCr3 (
+ VOID
+ );
+
+VOID
+EFIAPI
+ReAllocateMemoryForAP (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+VOID
+ResetAPs (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+EFI_STATUS
+PrepareMemoryForAPs (
+ OUT EFI_PHYSICAL_ADDRESS *WakeUpBuffer,
+ OUT VOID **StackAddressStart,
+ IN UINTN MaximumCPUsForThisSystem
+ );
+
+EFI_STATUS
+PrepareExchangeInfo (
+ OUT MP_CPU_EXCHANGE_INFO *ExchangeInfo,
+ IN VOID *StackAddressStart,
+ IN VOID *ApFunction,
+ IN EFI_PHYSICAL_ADDRESS WakeUpBuffer
+ );
+
+EFI_STATUS
+S3PrepareMemoryForAPs (
+ OUT EFI_PHYSICAL_ADDRESS *WakeUpBuffer,
+ OUT VOID **StackAddressStart
+ );
+
+EFI_STATUS
+S3PrepareExchangeInfo (
+ OUT MP_CPU_EXCHANGE_INFO *ExchangeInfo,
+ IN VOID *StackAddressStart,
+ IN VOID *ApFunction,
+ IN EFI_PHYSICAL_ADDRESS WakeUpBuffer
+ );
+
+BOOLEAN
+ApRunning (
+ VOID
+ );
+
+VOID
+ApProcWrapper (
+ VOID
+);
+
+UINTN
+SetIdtEntry (
+ IN UINTN FunctionPointer,
+ OUT INTERRUPT_GATE_DESCRIPTOR *IdtEntry
+);
+
+EFI_STATUS
+AllocateReservedMemoryBelow4G (
+ IN UINTN Size,
+ OUT VOID **Buffer
+ );
+
+VOID
+RedirectFarJump (
+ VOID
+ );
+
+VOID
+LegacyRegionAPCount (
+ VOID
+ );
+
+#endif
diff --git a/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/MpCpu.inf b/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/MpCpu.inf
new file mode 100644
index 0000000000..dfade3f5c5
--- /dev/null
+++ b/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/MpCpu.inf
@@ -0,0 +1,143 @@
+## @file
+# Component description file for MP Cpu module.
+#
+# This DXE Driver does processor initialization, configures multi-processor environment,
+# logs data to SMBIOS table for processor subclass and cache subclass, and installs
+# MP Services Protocol.
+#
+# Copyright (c) 1999 - 2015, 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 = 0x00010005
+ BASE_NAME = MpCpu
+ FILE_GUID = 4715BA19-6C49-46e0-B5DA-DE7CB9E059E2
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = InitializeCpu
+
+
+[sources.ia32]
+ Ia32/CpuAsm.asm
+ Ia32/CpuAsm.s | GCC
+ Ia32/MpProc.asm
+ Ia32/MpProc.s | GCC
+ Ia32/MPFuncs32.asm
+ Ia32/MPFuncs32.s | GCC
+ Ia32/MpCommon32.asm
+ Ia32/MpCommon32.s | GCC
+ Ia32/MemoryOperation.c
+ Ia32/Exception.c
+ Ia32/MpCpu.c
+ Ia32/InitializeFpu.s | GCC
+
+[sources.x64]
+ x64/Cpu.asm
+ x64/CpuAsm.asm
+ x64/Exception.c
+ x64/MemoryOperation.c
+ x64/MpCpu.c
+ x64/MpFuncs.asm
+ x64/CpuInitDxeGccDummy.c | GCC
+
+[sources]
+ Cpu.c
+ CpuDxe.h
+ MemoryAttribute.c
+ Microcode.c
+ MpCommon.c
+ MpService.c
+ MtrrSync.c
+ MiscFuncs.c
+
+[Protocols]
+ ## CONSUMES
+ gEfiMetronomeArchProtocolGuid
+
+ ## CONSUMES
+ ## PRODUCES
+ gEfiMpServiceProtocolGuid
+
+ ## CONSUMES
+ ## PRODUCES
+ gEfiCpuArchProtocolGuid
+
+ ## NOTIFY
+ gExitPmAuthProtocolGuid
+
+ ## CONSUMES
+ gEfiDxeSmmReadyToLockProtocolGuid
+
+ ## CONSUMES
+ gEfiSmmAccess2ProtocolGuid
+
+ ## CONSUMES
+ gEfiSmmControl2ProtocolGuid
+
+[Guids]
+ ## SOMETIMES_CONSUMES ## HOB
+ gEfiHtBistHobGuid
+
+ ## PRODUCES ## GUID
+ gEfiStatusCodeSpecificDataGuid
+
+ ## CONSUMES ## Event
+ gEfiEndOfDxeEventGroupGuid
+
+[Packages]
+ MdePkg/MdePkg.dec
+ IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec
+ BraswellPlatformPkg/BraswellPlatformPkg.dec
+
+[LibraryClasses]
+ BaseMemoryLib
+ DebugLib
+ ReportStatusCodeLib
+ BaseLib
+ UefiBootServicesTableLib
+ UefiRuntimeServicesTableLib
+ UefiLib
+ MemoryAllocationLib
+ DxeServicesTableLib
+ HobLib
+ UefiDriverEntryPoint
+ PcdLib
+ IoLib
+
+[Pcd.common]
+ ## SOMETIMES_CONSUMES
+ gIntelSiBasicPkgTokenSpaceGuid.CpuNumberOfThreadsPerCore
+
+ ## SOMETIMES_CONSUMES
+ gIntelSiBasicPkgTokenSpaceGuid.CpuNumberOfCoresPerDie
+
+ ## SOMETIMES_CONSUMES
+ gIntelSiBasicPkgTokenSpaceGuid.CpuNumberOfDiesPerPackage
+
+ ## SOMETIMES_CONSUMES
+ gIntelSiBasicPkgTokenSpaceGuid.CpuNumberOfPackages
+
+ ## SOMETIMES_CONSUMES
+ gIntelSiBasicPkgTokenSpaceGuid.PcdFlashMicroCodeRegionBase
+
+ ## SOMETIMES_CONSUMES
+ gIntelSiBasicPkgTokenSpaceGuid.PcdFlashMicroCodeRegionSize
+
+ ## SOMETIMES_CONSUMES
+ gIntelSiBasicPkgTokenSpaceGuid.PcdFlashMicroCodeOffset
+
+[Depex]
+ gEfiCpuIo2ProtocolGuid AND
+ gEfiVariableArchProtocolGuid AND
+ gEfiVariableWriteArchProtocolGuid
+
+
diff --git a/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/MpService.c b/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/MpService.c
new file mode 100644
index 0000000000..5157e766ae
--- /dev/null
+++ b/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/MpService.c
@@ -0,0 +1,1781 @@
+/** @file
+ Code which support multi-processor.
+
+ Copyright (c) 1999 - 2015, 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 "CpuDxe.h"
+#include "PlatformMpService.h"
+#include "MiscFuncs.h"
+
+#define MODULE_1_CPU0_APICID 4
+
+/**
+ @todo Add function description
+
+ @param[in] Event @todo Add argument description
+ @param[in] *Context @todo Add argument description
+
+**/
+VOID
+EFIAPI
+InitSmramDataContent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+extern EFI_METRONOME_ARCH_PROTOCOL *mMetronome;
+extern MP_SYSTEM_DATA *mMPSystemData;
+extern UINTN mCommonFeatures;
+extern volatile UINTN mSwitchToLegacyRegionCount;
+extern UINT32 mCommonCStateValue;
+
+static EFI_HANDLE mHandle = NULL;
+static volatile UINTN mFinishedCount = 0;
+
+EFI_MP_SERVICES_PROTOCOL mMpService = {
+ GetNumberOfProcessors,
+ GetProcessorInfo,
+ StartupAllAPs,
+ StartupThisAP,
+ SwitchBSP,
+ EnableDisableAP,
+ WhoAmI
+};
+
+EFI_PHYSICAL_ADDRESS mOriginalBuffer;
+EFI_PHYSICAL_ADDRESS mBackupBuffer;
+
+/**
+ Initialize the state information for the MP DXE Protocol.
+
+**/
+VOID
+EFIAPI
+MpServiceInitialize (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_EVENT LegacyBootEvent;
+ EFI_EVENT ExitBootServicesEvent;
+ EFI_EVENT ReAllocLegacyEvent;
+ EFI_EVENT ReAllocExitPmAuthEvent;
+ VOID *RegistrationLegacy;
+ VOID *RegistrationExitPmAuth;
+
+ LegacyBootEvent = NULL;
+ ExitBootServicesEvent = NULL;
+ ReAllocLegacyEvent = NULL;
+ ReAllocExitPmAuthEvent = NULL;
+ RegistrationLegacy = NULL;
+ RegistrationExitPmAuth = NULL;
+
+ //
+ // Save Mtrr Registers in global data areas
+ //
+ ReadMtrrRegisters ();
+
+ Status = InitializeMpSystemData ();
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+#if defined EFI_S3_RESUME
+ Status = gBS->CreateEvent (
+ EVT_NOTIFY_SIGNAL,
+ TPL_CALLBACK,
+ ReAllocateMemoryForAP,
+ NULL,
+ &ReAllocExitPmAuthEvent
+ );
+ ASSERT_EFI_ERROR (Status);
+ Status = gBS->RegisterProtocolNotify (
+ &gExitPmAuthProtocolGuid,
+ ReAllocExitPmAuthEvent,
+ &RegistrationExitPmAuth
+ );
+#else
+ Status = gBS->CreateEvent (
+ EVT_NOTIFY_SIGNAL,
+ TPL_CALLBACK,
+ ReAllocateMemoryForAP,
+ NULL,
+ &ReAllocExitPmAuthEvent
+ );
+ ASSERT_EFI_ERROR (Status);
+ Status = gBS->RegisterProtocolNotify (
+ &gExitPmAuthProtocolGuid,
+ ReAllocExitPmAuthEvent,
+ &RegistrationExitPmAuth
+ );
+ Status = gBS->CreateEvent (
+ EVT_NOTIFY_SIGNAL,
+ TPL_CALLBACK,
+ ReAllocateMemoryForAP,
+ NULL,
+ &ReAllocLegacyEvent
+ );
+ ASSERT_EFI_ERROR (Status);
+#endif
+ Status = EfiCreateEventLegacyBootEx (
+ TPL_CALLBACK,
+ (EFI_EVENT_NOTIFY)ResetAPs,
+ NULL,
+ &LegacyBootEvent
+ );
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ Status = gBS->CreateEvent (
+ EVT_SIGNAL_EXIT_BOOT_SERVICES,
+ TPL_CALLBACK,
+ (EFI_EVENT_NOTIFY)ResetAPs,
+ NULL,
+ &ExitBootServicesEvent
+ );
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ //
+ // Now install the MP services protocol.
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &mHandle,
+ &gEfiMpServiceProtocolGuid,
+ &mMpService,
+ NULL
+ );
+
+ if (EFI_ERROR (Status)) {
+
+Done:
+ if (LegacyBootEvent != NULL) {
+ gBS->CloseEvent (LegacyBootEvent);
+ }
+ if (ExitBootServicesEvent != NULL) {
+ gBS->CloseEvent (ExitBootServicesEvent);
+ }
+ gBS->FreePool (mMPSystemData);
+ }
+}
+
+/**
+ Implementation of GetNumberOfProcessors() service of MP Services Protocol.
+
+ This service retrieves the number of logical processor in the platform
+ and the number of those logical processors that are enabled on this boot.
+ This service may only be called from the BSP.
+
+ @param[in] This A pointer to the EFI_MP_SERVICES_PROTOCOL instance.
+ @param[out] NumberOfProcessors Pointer to the total number of logical processors in the system,
+ including the BSP and disabled APs.
+ @param[out] NumberOfEnabledProcessors Pointer to the number of enabled logical processors that exist
+ in system, including the BSP.
+
+ @retval EFI_SUCCESS Number of logical processors and enabled logical processors retrieved..
+ @retval EFI_DEVICE_ERROR Caller processor is AP.
+ @retval EFI_INVALID_PARAMETER NumberOfProcessors is NULL.
+ @retval EFI_INVALID_PARAMETER NumberOfEnabledProcessors is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+GetNumberOfProcessors (
+ IN EFI_MP_SERVICES_PROTOCOL *This,
+ OUT UINTN *NumberOfProcessors,
+ OUT UINTN *NumberOfEnabledProcessors
+ )
+{
+ UINTN CallerNumber;
+ UINTN Index;
+ CPU_DATA_BLOCK *CpuData;
+
+ //
+ // Check whether caller processor is BSP
+ //
+ WhoAmI (&mMpService, &CallerNumber);
+ if (CallerNumber != mMPSystemData->BSP) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Check parameter NumberOfProcessors and NumberOfEnabledProcessors
+ //
+ if (NumberOfProcessors == NULL || NumberOfEnabledProcessors == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *NumberOfProcessors = mMPSystemData->NumberOfCpus;
+ *NumberOfEnabledProcessors = 0;
+ for (Index = 0; Index < mMPSystemData->NumberOfCpus; Index++) {
+ CpuData = &mMPSystemData->CpuData[Index];
+ if (mMPSystemData->EnableSecondaryCpu) {
+ if (CpuData->State != CPU_STATE_DISABLED) {
+ (*NumberOfEnabledProcessors)++;
+ }
+ } else {
+ if (CpuData->State != CPU_STATE_DISABLED && !mMPSystemData->CpuData[Index].SecondaryCpu) {
+ (*NumberOfEnabledProcessors)++;
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Implementation of GetProcessorInfo() service of MP Services Protocol.
+
+ Gets detailed MP-related information on the requested processor at the
+ instant this call is made. This service may only be called from the BSP.
+
+ @param[in] This A pointer to the EFI_MP_SERVICES_PROTOCOL instance.
+ @param[in] ProcessorNumber The handle number of processor.
+ @param[out] ProcessorInfoBuffer A pointer to the buffer where information for the requested processor is deposited.
+
+ @retval EFI_SUCCESS Processor information successfully returned.
+ @retval EFI_DEVICE_ERROR Caller processor is AP.
+ @retval EFI_INVALID_PARAMETER ProcessorInfoBuffer is NULL
+ @retval EFI_NOT_FOUND Processor with the handle specified by ProcessorNumber does not exist.
+
+**/
+EFI_STATUS
+EFIAPI
+GetProcessorInfo (
+ IN EFI_MP_SERVICES_PROTOCOL *This,
+ IN UINTN ProcessorNumber,
+ OUT EFI_PROCESSOR_INFORMATION *ProcessorInfoBuffer
+ )
+{
+ UINTN CallerNumber;
+ CPU_DATA_BLOCK *CpuData;
+
+ //
+ // Check whether caller processor is BSP
+ //
+ WhoAmI (&mMpService, &CallerNumber);
+ if (CallerNumber != mMPSystemData->BSP) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Check parameter ProcessorInfoBuffer
+ //
+ if (ProcessorInfoBuffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Check whether processor with the handle specified by ProcessorNumber exists
+ //
+ if (ProcessorNumber >= mMPSystemData->NumberOfCpus) {
+ return EFI_NOT_FOUND;
+ }
+
+ CpuData = &mMPSystemData->CpuData[ProcessorNumber];
+
+ ProcessorInfoBuffer->ProcessorId = (UINT64) CpuData->ApicID;
+
+ //
+ // Get Status Flag of specified processor
+ //
+ ProcessorInfoBuffer->StatusFlag = 0;
+
+ ProcessorInfoBuffer->StatusFlag |= PROCESSOR_ENABLED_BIT;
+ if (!mMPSystemData->EnableSecondaryCpu) {
+ if (CpuData->SecondaryCpu) {
+ ProcessorInfoBuffer->StatusFlag &= ~PROCESSOR_ENABLED_BIT;
+ }
+ }
+
+ if (ProcessorNumber == mMPSystemData->BSP) {
+ ProcessorInfoBuffer->StatusFlag |= PROCESSOR_AS_BSP_BIT;
+ }
+
+ if (CpuData->Health == 0) {
+ ProcessorInfoBuffer->StatusFlag |= PROCESSOR_HEALTH_STATUS_BIT;
+ }
+
+ ProcessorInfoBuffer->Location.Package = (UINT32) CpuData->PhysicalLocation.Package;
+ ProcessorInfoBuffer->Location.Core = (UINT32) CpuData->PhysicalLocation.Core;
+ ProcessorInfoBuffer->Location.Thread = (UINT32) CpuData->PhysicalLocation.Thread;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ MP Service to get specified application processor (AP)
+ to execute a caller-provided code stream.
+
+ @param[in] This Pointer to MP Service Protocol
+ @param[in] Procedure The procedure to be assigned to AP.
+ @param[in] CpuNumber Number of the specified processor.
+ @param[in] WaitEvent If timeout, the event to be triggered after this AP finishes.
+ @param[in] TimeoutInMicroSecs The timeout value in microsecond. Zero means infinity.
+ @param[in] ProcArguments Argument for Procedure.
+ @param[out] Finished @todo Add argument description
+
+ @retval EFI_INVALID_PARAMETER Procudure is NULL.
+ @retval EFI_INVALID_PARAMETER Number of CPU out of range, or it belongs to BSP.
+ @retval EFI_INVALID_PARAMETER Specified CPU is not idle.
+ @retval EFI_SUCCESS The AP has finished.
+ @retval EFI_TIMEOUT Time goes out before the AP has finished.
+
+**/
+EFI_STATUS
+EFIAPI
+StartupThisAP (
+ IN EFI_MP_SERVICES_PROTOCOL *This,
+ IN EFI_AP_PROCEDURE Procedure,
+ IN UINTN CpuNumber,
+ IN EFI_EVENT WaitEvent OPTIONAL,
+ IN UINTN TimeoutInMicroSecs OPTIONAL,
+ IN VOID *ProcArguments OPTIONAL,
+ OUT BOOLEAN *Finished OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ CPU_DATA_BLOCK *CpuData;
+ UINT64 ExpectedTime;
+
+ //
+ // Check for invalid CPU number
+ //
+ if ((CpuNumber >= mMPSystemData->NumberOfCpus) || (CpuNumber == mMPSystemData->BSP)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Procedure == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Finished != NULL) {
+ *Finished = TRUE;
+ }
+
+ CpuData = &mMPSystemData->CpuData[CpuNumber];
+
+ //
+ // As a first step, check if processor is OK to start up code stream.
+ //
+ if (CpuData->State != CPU_STATE_IDLE) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ExpectedTime = CalculateTimeout (TimeoutInMicroSecs);
+
+ mMPSystemData->StartCount = 1;
+ mMPSystemData->FinishCount = 0;
+
+ WakeUpAp (
+ CpuData,
+ Procedure,
+ ProcArguments
+ );
+
+ while (TRUE) {
+ AsmAcquireMPLock (&CpuData->StateLock);
+ if (CpuData->State == CPU_STATE_FINISHED) {
+ CpuData->State = CPU_STATE_IDLE;
+ AsmReleaseMPLock (&CpuData->StateLock);
+ break;
+ }
+
+ AsmReleaseMPLock (&CpuData->StateLock);
+
+ if (CheckTimeout (ExpectedTime)) {
+ //
+ // Save data into private data structure, and create timer to poll AP state before exiting
+ //
+ mMPSystemData->StartedCpuNumber = CpuNumber;
+ mMPSystemData->WaitEvent = WaitEvent;
+ Status = gBS->SetTimer (
+ mMPSystemData->CheckThisAPEvent,
+ TimerPeriodic,
+ CPU_CHECK_AP_INTERVAL * MICROSECOND
+ );
+ return EFI_TIMEOUT;
+ }
+
+ gBS->Stall (CPU_CHECK_AP_INTERVAL * MICROSECOND);
+ }
+
+ CpuData->Finished = Finished;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ MP Service to get all the available application processors (APs)
+ to execute a caller-provided code stream.
+
+ @param[in] This Pointer to MP Service Protocol
+ @param[in] Procedure The procedure to be assigned to APs.
+ @param[in] SingleThread If true, all APs execute in block mode.
+ Otherwise, all APs exceute in non-block mode.
+ @param[in] WaitEvent If timeout, the event to be triggered after all APs finish.
+ @param[in] TimeoutInMicroSecs The timeout value in microsecond. Zero means infinity.
+ @param[in] ProcArguments Argument for Procedure.
+ @param[out] FailedCPUList If not NULL, all APs that fail to start will be recorded in the list.
+
+ @retval EFI_INVALID_PARAMETER Procudure is NULL.
+ @retval EFI_SUCCESS Only 1 logical processor exists.
+ @retval EFI_SUCCESS All APs have finished.
+ @retval EFI_TIMEOUT Time goes out before all APs have finished.
+
+**/
+EFI_STATUS
+EFIAPI
+StartupAllAPs (
+ IN EFI_MP_SERVICES_PROTOCOL *This,
+ IN EFI_AP_PROCEDURE Procedure,
+ IN BOOLEAN SingleThread,
+ IN EFI_EVENT WaitEvent OPTIONAL,
+ IN UINTN TimeoutInMicroSecs,
+ IN VOID *ProcArguments OPTIONAL,
+ OUT UINTN **FailedCPUList OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ CPU_DATA_BLOCK *CpuData;
+ CPU_DATA_BLOCK *NextCpuData;
+ UINTN ListIndex;
+ UINTN CpuNumber;
+ UINTN NextCpuNumber;
+ UINT64 ExpectedTime;
+ CPU_STATE APInitialState;
+ CPU_STATE CpuState;
+
+ //
+ // Check for valid procedure for APs
+ //
+ if (Procedure == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (mMPSystemData->NumberOfCpus == 1) {
+ return EFI_SUCCESS;
+ }
+
+ ExpectedTime = CalculateTimeout (TimeoutInMicroSecs);
+
+ ListIndex = 0;
+ CpuData = NULL;
+
+ mMPSystemData->FinishCount = 0;
+ mMPSystemData->StartCount = 0;
+ APInitialState = CPU_STATE_READY;
+
+ for (CpuNumber = 0; CpuNumber < mMPSystemData->NumberOfCpus; CpuNumber++) {
+ CpuData = &mMPSystemData->CpuData[CpuNumber];
+
+ //
+ // Get APs prepared, and put failing APs into FailedCPUList
+ // If "SingleThread", one AP will be put to ready state.
+ // Once this AP finishes its task, the next AP is put to Ready state.
+ // This process continues until all APs are put into Ready State
+ // if not "SingleThread", all APs are put to ready state at the same time
+ //
+ if (CpuNumber != mMPSystemData->BSP) {
+ if (CpuData->State == CPU_STATE_IDLE) {
+ mMPSystemData->StartCount++;
+
+ AsmAcquireMPLock (&CpuData->StateLock);
+ CpuData->State = APInitialState;
+ AsmReleaseMPLock (&CpuData->StateLock);
+
+ if (SingleThread) {
+ APInitialState = CPU_STATE_BLOCKED;
+ }
+
+ } else if (FailedCPUList != NULL) {
+ *FailedCPUList[ListIndex] = CpuNumber;
+ ListIndex++;
+ }
+ }
+ }
+
+ while (TRUE) {
+ for (CpuNumber = 0; CpuNumber < mMPSystemData->NumberOfCpus; CpuNumber++) {
+ CpuData = &mMPSystemData->CpuData[CpuNumber];
+ if (CpuNumber == mMPSystemData->BSP) {
+ continue;
+ }
+ CpuState = CpuData->State;
+ switch (CpuState) {
+ case CPU_STATE_READY:
+ WakeUpAp (
+ CpuData,
+ Procedure,
+ ProcArguments
+ );
+ break;
+
+ case CPU_STATE_FINISHED:
+ mMPSystemData->FinishCount++;
+ if (SingleThread) {
+ Status = GetNextBlockedCpuNumber (&NextCpuNumber);
+ if (!EFI_ERROR (Status)) {
+ NextCpuData = &mMPSystemData->CpuData[NextCpuNumber];
+ AsmAcquireMPLock (&NextCpuData->StateLock);
+ NextCpuData->State = CPU_STATE_READY;
+ AsmReleaseMPLock (&NextCpuData->StateLock);
+ }
+ }
+ AsmAcquireMPLock (&CpuData->StateLock);
+ CpuData->State = CPU_STATE_IDLE;
+ AsmReleaseMPLock (&CpuData->StateLock);
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ if (mMPSystemData->FinishCount == mMPSystemData->StartCount) {
+ return EFI_SUCCESS;
+ }
+
+ if (CheckTimeout (ExpectedTime)) {
+ //
+ // Save data into private data structure, and create timer to poll AP state before exiting
+ //
+ mMPSystemData->Procedure = Procedure;
+ mMPSystemData->ProcArguments = ProcArguments;
+ mMPSystemData->SingleThread = SingleThread;
+ mMPSystemData->WaitEvent = WaitEvent;
+
+ Status = gBS->SetTimer (
+ mMPSystemData->CheckAllAPsEvent,
+ TimerPeriodic,
+ CPU_CHECK_AP_INTERVAL * MICROSECOND
+ );
+ return EFI_TIMEOUT;
+ }
+
+ gBS->Stall (CPU_CHECK_AP_INTERVAL * MICROSECOND);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ MP Service to makes the current BSP into an AP and then switches the
+ designated AP into the AP. This procedure is usually called after a CPU
+ test that has found that BSP is not healthy to continue it's responsbilities.
+
+ @param[in] This Pointer to MP Service Protocol.
+ @param[in] CpuNumber The number of the specified AP.
+ @param[in] EnableOldBSP Whether to enable or disable the original BSP.
+
+ @retval EFI_INVALID_PARAMETER Number for Specified AP out of range.
+ @retval EFI_INVALID_PARAMETER Number of specified CPU belongs to BSP.
+ @retval EFI_NOT_READY Specified AP is not idle.
+ @retval EFI_SUCCESS BSP successfully switched.
+
+**/
+EFI_STATUS
+EFIAPI
+SwitchBSP (
+ IN EFI_MP_SERVICES_PROTOCOL *This,
+ IN UINTN CpuNumber,
+ IN BOOLEAN EnableOldBSP
+ )
+{
+ EFI_STATUS Status;
+ EFI_CPU_ARCH_PROTOCOL *CpuArch;
+ BOOLEAN OldInterruptState;
+ CPU_DATA_BLOCK *CpuData;
+ CPU_STATE CpuState;
+
+ //
+ // Check if the specified CPU number is valid
+ //
+ if (CpuNumber >= mMPSystemData->NumberOfCpus) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Check if the specified CPU is already BSP
+ //
+ if (CpuNumber == mMPSystemData->BSP) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ CpuData = &mMPSystemData->CpuData[CpuNumber];
+ if (CpuData->State != CPU_STATE_IDLE) {
+ return EFI_NOT_READY;
+ }
+ //
+ // Before send both BSP and AP to a procedure to exchange their roles,
+ // interrupt must be disabled. This is because during the exchange role
+ // process, 2 CPU may use 1 stack. If interrupt happens, the stack will
+ // be corrputed, since interrupt return address will be pushed to stack
+ // by hardware.
+ //
+ CpuArch = mMPSystemData->CpuArch;
+ (CpuArch->GetInterruptState)(CpuArch, &OldInterruptState);
+ if (OldInterruptState) {
+ Status = CpuArch->DisableInterrupt (CpuArch);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ //
+ // Unprogram virtual wire mode for the old BSP
+ //
+ ProgramVirtualWireMode (FALSE);
+ SetApicBSPBit (FALSE);
+
+ mMPSystemData->BSPInfo.State = CPU_SWITCH_STATE_IDLE;
+ mMPSystemData->BSPInfo.Lock = VacantFlag;
+ mMPSystemData->APInfo.State = CPU_SWITCH_STATE_IDLE;
+ mMPSystemData->APInfo.Lock = VacantFlag;
+
+ //
+ // Need to wakeUp AP (future BSP)
+ //
+ WakeUpAp (
+ CpuData,
+ (EFI_AP_PROCEDURE)FutureBSPProc,
+ mMPSystemData
+ );
+
+ AsmExchangeRole (&mMPSystemData->BSPInfo, &mMPSystemData->APInfo);
+
+ //
+ // The new BSP has come out. Since it carries the register value of the AP, need
+ // to pay attention to variable which are stored in registers (due to optimization)
+ //
+ SetApicBSPBit (TRUE);
+ ProgramVirtualWireMode (TRUE);
+
+ if (OldInterruptState) {
+ Status = CpuArch->EnableInterrupt (CpuArch);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ CpuData = &mMPSystemData->CpuData[mMPSystemData->BSP];
+ while (TRUE) {
+ AsmAcquireMPLock (&CpuData->StateLock);
+ CpuState = CpuData->State;
+ AsmReleaseMPLock (&CpuData->StateLock);
+
+ if (CpuState == CPU_STATE_FINISHED) {
+ break;
+ }
+ }
+
+ Status = ChangeCpuState (mMPSystemData->BSP, EnableOldBSP, EFI_CPU_CAUSE_NOT_DISABLED);
+ mMPSystemData->BSP = CpuNumber;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure enables Or disables APs.
+
+ @param[in] This Pointer to MP Service Protocol.
+ @param[in] CpuNumber The number of the specified AP.
+ @param[in] NewAPState Indicate new desired AP state
+ @param[in] HealthState If not NULL, it points to the value that specifies
+ the new health status of the AP. If it is NULL,
+ this parameter is ignored.
+
+ @retval EFI_INVALID_PARAMETER Input paramters were not correct.
+ @retval EFI_SUCCESS Function completed successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+EnableDisableAP (
+ IN EFI_MP_SERVICES_PROTOCOL *This,
+ IN UINTN CpuNumber,
+ IN BOOLEAN NewAPState,
+ IN UINT32 *HealthState OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ CPU_DATA_BLOCK *CpuData;
+
+ //
+ // Check for valid input parameters.
+ //
+ if (CpuNumber >= mMPSystemData->NumberOfCpus || CpuNumber == mMPSystemData->BSP) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ CpuData = &mMPSystemData->CpuData[CpuNumber];
+ Status = ChangeCpuState (CpuNumber, NewAPState, EFI_CPU_CAUSE_USER_SELECTION);
+
+ if (HealthState != NULL) {
+ CopyMem (&CpuData->Health, HealthState, sizeof (UINT32));
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure returns the calling CPU handle.
+
+ @param[in] This Pointer to MP Service Protocol.
+ @param[out] CpuNumber The number of the specified AP.
+
+ @retval EFI_SUCCESS Function completed successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+WhoAmI (
+ IN EFI_MP_SERVICES_PROTOCOL *This,
+ OUT UINTN *CpuNumber
+ )
+{
+ UINTN ApicID;
+ UINTN NumOfCpus;
+ UINTN Index;
+
+ ApicID = GetApicID (NULL, NULL);
+
+ NumOfCpus = mMPSystemData->NumberOfCpus;
+
+ for (Index = 0; Index < NumOfCpus; Index++) {
+ if (ApicID == mMPSystemData->CpuData[Index].ApicID) {
+ break;
+ }
+ }
+
+ *CpuNumber = Index;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Searches the HOB list provided by the core to find
+ if a MP guided HOB list exists or not. If it does, it copies it to the driver
+ data area, else returns 0
+
+ @param[in] MPSystemData Pointer to an MP_SYSTEM_DATA structure
+
+ @retval EFI_SUCCESS Success
+ @retval Others HOB not found or else
+
+**/
+EFI_STATUS
+GetMpBistStatus (
+ IN MP_SYSTEM_DATA *MPSystemData
+ )
+{
+ EFI_STATUS Status;
+ VOID *DataInHob;
+ UINTN DataSize;
+ EFI_PEI_HOB_POINTERS GuidHob;
+
+ //
+ // Get Hob list
+ //
+ DataInHob = NULL;
+ DataSize = 0;
+ GuidHob.Raw = GetHobList ();
+
+ if (GuidHob.Raw == NULL) {
+ DEBUG ((EFI_D_ERROR, "No HOBs found\n"));
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Check for MP Data Hob.
+ //
+ GuidHob.Raw = GetNextGuidHob (&gEfiHtBistHobGuid, GuidHob.Raw);
+ if (GuidHob.Raw != NULL) {
+ DataInHob = GET_GUID_HOB_DATA (GuidHob.Guid);
+ DataSize = GET_GUID_HOB_DATA_SIZE(GuidHob.Guid);
+ Status = EFI_SUCCESS;
+ } else {
+ Status = EFI_NOT_FOUND;
+ }
+
+ //
+ // This is the MP HOB. So, copy all the data.
+ //
+ if (!(EFI_ERROR (Status))) {
+ if(NULL == MPSystemData->BistHobData){
+ gBS->AllocatePool(
+ EfiACPIMemoryNVS,
+ DataSize,
+ (VOID **)&MPSystemData->BistHobData
+ );
+ }
+ gBS->CopyMem (MPSystemData->BistHobData, DataInHob, DataSize);
+ MPSystemData->BistHobSize = DataSize;
+ }
+
+ return Status;
+}
+
+/**
+ Allocate data pool for MP information and fill data in it.
+
+ @param[out] WakeUpBuffer The address of wakeup buffer.
+ @param[out] StackAddressStart The start address of APs's stacks.
+ @param[in] MaximumCPUsForThisSystem Maximum CPUs in this system.
+
+ @retval EFI_SUCCESS Function successfully executed.
+ @retval Other Error occurred while allocating memory.
+
+**/
+EFI_STATUS
+AllocateMemoryAndFillData (
+ OUT EFI_PHYSICAL_ADDRESS WakeUpBuffer,
+ OUT VOID *StackAddressStart,
+ IN UINTN MaximumCPUsForThisSystem
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // First check if the MP data structures and AP rendezvous routine have been
+ // supplied by the PEIMs that executed in early boot stage.
+ //
+
+ //
+ // Clear the data structure area first.
+ //
+ gBS->SetMem (mMPSystemData, sizeof (MP_SYSTEM_DATA), 0);
+
+ Status = GetMpBistStatus (mMPSystemData);
+
+ mAcpiCpuData->CpuPrivateData = (EFI_PHYSICAL_ADDRESS)(UINTN)(&(mMPSystemData->S3DataPointer));
+ mAcpiCpuData->APState = 1;
+ mAcpiCpuData->WakeUpBuffer = WakeUpBuffer;
+ mAcpiCpuData->StackAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)(StackAddressStart);
+
+ Status = PrepareGdtIdtForAP ((IA32_DESCRIPTOR *) (UINTN) mAcpiCpuData->GdtrProfile, (IA32_DESCRIPTOR *) (UINTN) mAcpiCpuData->IdtrProfile);
+
+ //
+ // First BSP fills and inits all known values, including it's own records.
+ //
+ mMPSystemData->APSerializeLock = VacantFlag;
+ mMPSystemData->NumberOfCpus = 1;
+ mMPSystemData->EnableSecondaryCpu = 1;
+
+ //
+ // Record these CPU configuration data (both for normal boot and for S3 use)
+ //
+ mMPSystemData->CpuArch = NULL;
+ gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **) &mMPSystemData->CpuArch);
+
+ mMPSystemData->MaximumCpusForThisSystem = MaximumCPUsForThisSystem;
+
+ mMPSystemData->BSP = 0;
+
+ FillInProcessorInformation (mMPSystemData, TRUE, 0);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Wake up APs for the first time to count their number and collect BIST data.
+
+ @param[in] WakeUpBuffer Address of the wakeup buffer.
+
+ @retval EFI_SUCCESS Function successfully finishes.
+
+**/
+EFI_STATUS
+CountApNumberAndCollectBist (
+ IN EFI_PHYSICAL_ADDRESS WakeUpBuffer
+ )
+{
+ MP_CPU_EXCHANGE_INFO *ExchangeInfo;
+ UINTN Index;
+
+ //
+ // Send INIT IPI - SIPI to all APs
+ //
+ SendInterrupt (BROADCAST_MODE_ALL_EXCLUDING_SELF, 0, 0, DELIVERY_MODE_INIT, TRIGGER_MODE_EDGE, TRUE);
+ SendInterrupt (
+ BROADCAST_MODE_ALL_EXCLUDING_SELF,
+ 0,
+ (UINT32) RShiftU64 (WakeUpBuffer, 12),
+ DELIVERY_MODE_SIPI,
+ TRIGGER_MODE_EDGE,
+ TRUE
+ );
+
+ //
+ // Wait for task to complete and then exit.
+ //
+ gBS->Stall (200 * MICROSECOND);
+
+ ExchangeInfo = (MP_CPU_EXCHANGE_INFO *) (UINTN) (WakeUpBuffer + MP_CPU_EXCHANGE_INFO_OFFSET);
+
+ for (Index = 0; Index < MAXIMUM_CPU_NUMBER; Index++) {
+ if (ExchangeInfo->BistBuffer[Index].Number == 1) {
+ ExchangeInfo->BistBuffer[Index].Number = (UINT32) mMPSystemData->NumberOfCpus++;
+ }
+ }
+ mAcpiCpuData->NumberOfCpus = (UINT32) mMPSystemData->NumberOfCpus;
+
+ ExchangeInfo->InitFlag = 0;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Wake up APs for the second time to collect detailed information.
+
+ @param[in] WakeUpBuffer Address of the wakeup buffer.
+
+ @retval EFI_SUCCESS Function successfully finishes.
+
+**/
+EFI_STATUS
+PollForInitialization (
+ IN EFI_PHYSICAL_ADDRESS WakeUpBuffer
+ )
+{
+ MP_CPU_EXCHANGE_INFO *ExchangeInfo;
+
+ ExchangeInfo = (MP_CPU_EXCHANGE_INFO *) (UINTN) (WakeUpBuffer + MP_CPU_EXCHANGE_INFO_OFFSET);
+ ExchangeInfo->ApFunction = (VOID *) (UINTN) DetailedInitialization;
+
+ SendInterrupt (BROADCAST_MODE_ALL_EXCLUDING_SELF, 0, 0, DELIVERY_MODE_INIT, TRIGGER_MODE_EDGE, TRUE);
+ SendInterrupt (
+ BROADCAST_MODE_ALL_EXCLUDING_SELF,
+ 0,
+ (UINT32) RShiftU64 (WakeUpBuffer, 12),
+ DELIVERY_MODE_SIPI,
+ TRIGGER_MODE_EDGE,
+ TRUE
+ );
+
+ //
+ // Wait until all APs finish
+ //
+ while (mFinishedCount < mAcpiCpuData->NumberOfCpus - 1) {
+ CpuPause ();
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ @todo Add function description
+
+ @param[in] Location @todo Add argument description
+
+ @retval EFI_SUCCESS @todo Add argument description
+
+**/
+EFI_STATUS
+FillInCpuLocation (
+ IN EFI_CPU_PHYSICAL_LOCATION *Location
+ )
+{
+ UINT32 ApicId;
+ UINT32 LevelType;
+ UINT32 LevelBits;
+ UINT32 RegEax;
+ UINT32 RegEbx;
+ UINT32 RegEcx;
+ UINT8 Shift;
+ UINT8 Bits;
+ UINT32 Mask;
+ BOOLEAN HyperThreadingEnabled;
+
+ AsmCpuid (EFI_CPUID_VERSION_INFO, NULL, &RegEbx, NULL, NULL);
+ ApicId = (RegEbx >> 24);
+
+ AsmCpuid (EFI_CPUID_SIGNATURE, &RegEax, NULL, NULL, NULL);
+ if (RegEax >= EFI_CPUID_CORE_TOPOLOGY) {
+ LevelBits = 0;
+ LevelType = 0;
+ do {
+ AsmCpuidEx (EFI_CPUID_CORE_TOPOLOGY, LevelType, &RegEax, &RegEbx, &RegEcx, NULL);
+ LevelType = ((RegEcx >> 8) & 0xFF);
+ switch (LevelType) {
+ case 1: //Thread
+ Location->Thread = ApicId & ((1 << (RegEax & 0x0F)) - 1);
+ Location->Thread >>= LevelBits;
+ LevelBits = RegEax & 0x0F;
+ break;
+ case 2: //Core
+ Location->Core = ApicId & ((1 << (RegEax & 0x0F)) - 1);
+ Location->Core >>= LevelBits;
+ LevelBits = RegEax & 0x0F;
+ break;
+ default: //End of Level
+ Location->Package = ApicId >> LevelBits;
+ break;
+ }
+ } while (!(RegEax == 0 && RegEbx == 0));
+ } else {
+
+ AsmCpuid (EFI_CPUID_VERSION_INFO, NULL, &RegEbx, NULL, NULL);
+ Bits = 0;
+ Shift = (UINT8)((RegEbx >> 16) & 0xFF);
+
+ Mask = Shift - 1;
+ while (Shift > 1) {
+ Shift >>= 1;
+ Bits++;
+ }
+
+ HyperThreadingEnabled = FALSE;
+ AsmCpuidEx (EFI_CPUID_CACHE_PARAMS, 0, &RegEax, NULL, NULL, NULL);
+ if (Mask > (RegEax >> 26)) {
+ HyperThreadingEnabled = TRUE;
+ }
+
+ Location->Package = (ApicId >> Bits);
+ if (HyperThreadingEnabled) {
+ Location->Core = (ApicId & Mask) >> 1;
+ Location->Thread = (ApicId & Mask) & 1;
+ } else {
+ Location->Core = (ApicId & Mask);
+ Location->Thread = 0;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Initialize multiple processors and collect MP related data
+
+ @retval EFI_SUCCESS Multiple processors get initialized and data collected successfully
+
+ @retval Other The operation failed due to some reason
+
+**/
+EFI_STATUS
+InitializeMpSystemData (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINT32 MaxThreadsPerCore;
+ UINT32 MaxCoresPerDie;
+ UINT32 MaxDiesPerPackage;
+ UINT32 MaxPackages;
+ VOID *StackAddressStart;
+ EFI_PHYSICAL_ADDRESS WakeUpBuffer;
+ MP_CPU_EXCHANGE_INFO *ExchangeInfo;
+ UINTN Index;
+ EFI_CPU_ARCH_PROTOCOL *CpuArch;
+ BOOLEAN mInterruptState;
+ CPU_DATA_BLOCK *CpuData;
+ UINTN MaximumCPUsForThisSystem;
+
+ ProgramVirtualWireMode (TRUE);
+ MaxThreadsPerCore = PcdGet32 (CpuNumberOfThreadsPerCore);
+ MaxCoresPerDie = PcdGet32(CpuNumberOfCoresPerDie);
+ MaxDiesPerPackage = PcdGet32(CpuNumberOfDiesPerPackage);
+ MaxPackages = PcdGet32(CpuNumberOfPackages);
+
+ MaximumCPUsForThisSystem = MaxThreadsPerCore * MaxCoresPerDie * MaxDiesPerPackage * MaxPackages;
+
+ Status = PrepareMemoryForAPs (
+ &WakeUpBuffer,
+ &StackAddressStart,
+ MaximumCPUsForThisSystem
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ mOriginalBuffer = WakeUpBuffer;
+
+ Status = gBS->AllocatePages (
+ AllocateAnyPages,
+ EfiBootServicesData,
+ 1,
+ &mBackupBuffer
+ );
+
+ Status = AllocateMemoryAndFillData (
+ WakeUpBuffer,
+ StackAddressStart,
+ MaximumCPUsForThisSystem
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ ExchangeInfo = (MP_CPU_EXCHANGE_INFO *) (UINTN) (WakeUpBuffer + MP_CPU_EXCHANGE_INFO_OFFSET);
+ Status = PrepareExchangeInfo (
+ ExchangeInfo,
+ StackAddressStart,
+ NULL,
+ WakeUpBuffer
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ CpuArch = mMPSystemData->CpuArch;
+ CpuArch->GetInterruptState (CpuArch, &mInterruptState);
+ CpuArch->DisableInterrupt (CpuArch);
+
+ //
+ // For B stepping and above use broadcast
+ //
+ CountApNumberAndCollectBist (WakeUpBuffer);
+ ExchangeInfo->WakeUpApManner = WakeUpApCounterInit;
+ PollForInitialization (WakeUpBuffer);
+
+ ExchangeInfo->WakeUpApManner = (WAKEUP_AP_MANNER) WakeUpApPerHltLoop;
+ ExchangeInfo->ApFunction = (VOID *) (UINTN) ApProcWrapper;
+ if (mInterruptState) {
+ CpuArch->EnableInterrupt (CpuArch);
+ }
+
+ for (Index = 1; Index < mMPSystemData->NumberOfCpus; Index++) {
+ CpuData = &mMPSystemData->CpuData[Index];
+ if (CpuData->Health != 0) {
+ REPORT_STATUS_CODE_EX (
+ EFI_ERROR_MAJOR | EFI_ERROR_CODE,
+ EFI_COMPUTING_UNIT_HOST_PROCESSOR | EFI_CU_HP_EC_SELF_TEST,
+ (UINT32) Index,
+ &gEfiCallerIdGuid,
+ NULL,
+ NULL,
+ 0
+ );
+ }
+
+ }
+
+ Status = gBS->CreateEvent (
+ EVT_TIMER | EVT_NOTIFY_SIGNAL,
+ TPL_CALLBACK,
+ (EFI_EVENT_NOTIFY)CheckAllAPsStatus,
+ NULL,
+ &mMPSystemData->CheckAllAPsEvent
+ );
+ Status = gBS->CreateEvent (
+ EVT_TIMER | EVT_NOTIFY_SIGNAL,
+ TPL_CALLBACK,
+ (EFI_EVENT_NOTIFY)CheckThisAPStatus,
+ NULL,
+ &mMPSystemData->CheckThisAPEvent
+ );
+
+ SaveBspMtrrForS3 ();
+ CopyMem ((VOID *) (UINTN) mBackupBuffer, (VOID *) (UINTN) mOriginalBuffer, EFI_PAGE_SIZE);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Wrapper function for all procedures assigned to AP via MP service protocol.
+ It controls states of AP and invokes assigned precedure.
+
+**/
+VOID
+ApProcWrapper (
+ VOID
+ )
+{
+ EFI_AP_PROCEDURE Procedure;
+ VOID *Parameter;
+ UINTN CpuNumber;
+ CPU_DATA_BLOCK *CpuData;
+
+ WhoAmI (&mMpService, &CpuNumber);
+ CpuData = &mMPSystemData->CpuData[CpuNumber];
+
+ //
+ // Now let us check it out.
+ //
+ AsmAcquireMPLock (&CpuData->ProcedureLock);
+ Procedure = CpuData->Procedure;
+ Parameter = CpuData->Parameter;
+ AsmReleaseMPLock (&CpuData->ProcedureLock);
+
+ if (Procedure != NULL) {
+ AsmAcquireMPLock (&CpuData->StateLock);
+ CpuData->State = CPU_STATE_BUSY;
+ AsmReleaseMPLock (&CpuData->StateLock);
+
+ Procedure (Parameter);
+
+ //
+ // if BSP is switched to AP, it continue execute from here, but it carries register state
+ // of the old AP, so need to reload CpuData (might be stored in a register after compiler
+ // optimization) to make sure it points to the right data
+ //
+ WhoAmI (&mMpService, &CpuNumber);
+ CpuData = &mMPSystemData->CpuData[CpuNumber];
+
+ AsmAcquireMPLock (&CpuData->ProcedureLock);
+ CpuData->Procedure = NULL;
+ AsmReleaseMPLock (&CpuData->ProcedureLock);
+
+ AsmAcquireMPLock (&CpuData->StateLock);
+ CpuData->State = CPU_STATE_FINISHED;
+ AsmReleaseMPLock (&CpuData->StateLock);
+ }
+}
+
+/**
+ Procedure for detailed initialization of APs. It will be assigned to all APs while
+ they are waken up for the second time.
+
+**/
+VOID
+DetailedInitialization (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINT32 FailedRevision;
+
+ CpuInitFloatPointUnit ();
+
+ AsmAcquireMPLock (&mMPSystemData->APSerializeLock);
+
+ Status = InitializeMicrocode (
+ (EFI_CPU_MICROCODE_HEADER **) (UINTN) mAcpiCpuData->MicrocodePointerBuffer,
+ &FailedRevision,
+ FALSE
+ );
+
+ //
+ // Save Mtrr Registers in global data areas
+ //
+ MpMtrrSynchUp (NULL);
+
+ ProgramVirtualWireMode (FALSE);
+
+ FillInProcessorInformation (mMPSystemData, FALSE, 0);
+
+ mFinishedCount++;
+
+ AsmReleaseMPLock (&mMPSystemData->APSerializeLock);
+}
+
+/**
+ @todo Add function description
+
+ @param[in] MPSystemData - @todo add argument description
+
+ @retval - @todo add return values
+
+**/
+VOID
+FutureBSPProc (
+ IN MP_SYSTEM_DATA *MPSystemData
+ )
+{
+ AsmExchangeRole (&MPSystemData->APInfo, &MPSystemData->BSPInfo);
+ return ;
+}
+
+/**
+ This function is called by all processors (both BSP and AP) once and collects MP related data
+
+ @param[in] MPSystemData Pointer to the data structure containing MP related data
+ @param[in] BSP TRUE if the CPU is BSP
+ @param[in] BistParam BIST (build-in self test) data for the processor. This data
+ is only valid for processors that are waked up for the 1st
+ time in this CPU DXE driver.
+
+ @retval EFI_SUCCESS Data for the processor collected and filled in
+
+**/
+EFI_STATUS
+FillInProcessorInformation (
+ IN MP_SYSTEM_DATA *MPSystemData,
+ IN BOOLEAN BSP,
+ IN UINT32 BistParam
+ )
+{
+ UINT32 Health;
+ UINT32 ApicID;
+ CPU_DATA_BLOCK *CpuData;
+ UINT32 BIST;
+ UINTN CpuNumber;
+ UINTN Index;
+ UINTN Count;
+ MP_CPU_EXCHANGE_INFO *ExchangeInfo;
+
+ ApicID = GetApicID (NULL, NULL);
+ BIST = 0;
+
+ if (BSP) {
+ CpuNumber = 0;
+ BIST = BistParam;
+ } else {
+ ExchangeInfo = (MP_CPU_EXCHANGE_INFO *) (UINTN) (mAcpiCpuData->WakeUpBuffer + MP_CPU_EXCHANGE_INFO_OFFSET);
+ CpuNumber = ExchangeInfo->BistBuffer[ApicID].Number;
+ BIST = ExchangeInfo->BistBuffer[ApicID].BIST;
+ }
+
+ CpuData = &MPSystemData->CpuData[CpuNumber];
+ CpuData->SecondaryCpu = IsSecondaryThread ();
+ CpuData->ApicID = ApicID;
+ CpuData->Procedure = NULL;
+ CpuData->Parameter = NULL;
+ CpuData->StateLock = VacantFlag;
+ CpuData->ProcedureLock = VacantFlag;
+ CpuData->State = CPU_STATE_IDLE;
+
+ Health = BIST;
+ Count = MPSystemData->BistHobSize / sizeof(BIST_HOB_DATA);
+ for (Index = 0; Index < Count; Index++) {
+ if (ApicID == MPSystemData->BistHobData[Index].ApicId) {
+ Health = MPSystemData->BistHobData[Index].Health;
+ }
+ }
+
+ if (Health > 0) {
+ CpuData->State = CPU_STATE_DISABLED;
+ MPSystemData->DisableCause[CpuNumber] = EFI_CPU_CAUSE_SELFTEST_FAILURE;
+ } else {
+ MPSystemData->DisableCause[CpuNumber] = EFI_CPU_CAUSE_NOT_DISABLED;
+ }
+
+ //
+ // Get Core and Thread number
+ //
+ CpuData->NumberOfCores = PcdGet32(CpuNumberOfCoresPerDie);
+
+ CpuData->NumberOfThreads = PcdGet32(CpuNumberOfThreadsPerCore);
+
+ FillInCpuLocation (&CpuData->PhysicalLocation);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ @todo Add function description
+
+ @param[in] Enable - @todo add argument description
+
+ @retval EFI_SUCCESS - @todo Add description for return value
+
+**/
+EFI_STATUS
+SetApicBSPBit (
+ IN BOOLEAN Enable
+ )
+{
+ UINT64 ApicBaseReg;
+
+ ApicBaseReg = AsmReadMsr64 (EFI_MSR_IA32_APIC_BASE);
+
+ if (Enable) {
+ ApicBaseReg |= B_EFI_MSR_IA32_APIC_BASE_BSP;
+ } else {
+ ApicBaseReg &= (~(UINT64)(B_EFI_MSR_IA32_APIC_BASE_BSP | 0xFF));
+ }
+
+ AsmWriteMsr64 (EFI_MSR_IA32_APIC_BASE, ApicBaseReg);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ @todo Add function description
+
+ @param[in] CpuNumber - @todo add argument description
+ @param[in] NewState - @todo add argument description
+ @param[in] Cause - @todo add argument description
+
+ @retval EFI_SUCCESS - @todo Add description for return value
+
+**/
+EFI_STATUS
+ChangeCpuState (
+ IN UINTN CpuNumber,
+ IN BOOLEAN NewState,
+ IN EFI_CPU_STATE_CHANGE_CAUSE Cause
+ )
+{
+ CPU_DATA_BLOCK *CpuData;
+ EFI_COMPUTING_UNIT_CPU_DISABLED_ERROR_DATA ErrorData;
+
+ CpuData = &mMPSystemData->CpuData[CpuNumber];
+
+ mMPSystemData->DisableCause[CpuNumber] = Cause;
+
+ if (!NewState) {
+ AsmAcquireMPLock (&CpuData->StateLock);
+ CpuData->State = CPU_STATE_DISABLED;
+ AsmReleaseMPLock (&CpuData->StateLock);
+
+ ErrorData.DataHeader.HeaderSize = sizeof (EFI_STATUS_CODE_DATA);
+ ErrorData.DataHeader.Size = sizeof (EFI_COMPUTING_UNIT_CPU_DISABLED_ERROR_DATA) - sizeof (EFI_STATUS_CODE_DATA);
+ CopyMem (
+ &ErrorData.DataHeader.Type,
+ &gEfiStatusCodeSpecificDataGuid,
+ sizeof (EFI_GUID)
+ );
+ ErrorData.Cause = Cause;
+ ErrorData.SoftwareDisabled = TRUE;
+ REPORT_STATUS_CODE_EX (
+ EFI_ERROR_MINOR | EFI_ERROR_CODE,
+ EFI_COMPUTING_UNIT_HOST_PROCESSOR | EFI_CU_EC_DISABLED,
+ (UINT32) CpuNumber,
+ &gEfiCallerIdGuid,
+ NULL,
+ (EFI_STATUS_CODE_DATA *) &ErrorData,
+ sizeof(EFI_COMPUTING_UNIT_CPU_DISABLED_ERROR_DATA)
+ );
+ } else {
+ AsmAcquireMPLock (&CpuData->StateLock);
+ CpuData->State = CPU_STATE_IDLE;
+ AsmReleaseMPLock (&CpuData->StateLock);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ @todo Add function description
+
+ @retval @todo add return values
+
+**/
+BOOLEAN
+IsSecondaryThread (
+ VOID
+ )
+{
+ UINT32 ApicID;
+ UINT8 CpuPerCore;
+ UINT32 Mask;
+
+ ApicID = GetApicID (NULL, NULL);
+
+ CpuPerCore = (UINT8)PcdGet32(CpuNumberOfThreadsPerCore);
+ if (CpuPerCore == 1) {
+ return FALSE;
+ }
+
+ //
+ // Assume 1 Core has no more than 8 threads
+ //
+ if (CpuPerCore == 2) {
+ Mask = 0x1;
+ } else if (CpuPerCore <= 4) {
+ Mask = 0x3;
+ } else {
+ Mask = 0x7;
+ }
+
+ if (ApicID & Mask) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ If timeout occurs in StartupAllAps(), a timer is set, which invokes this
+ procedure periodically to check whether all APs have finished.
+
+ @param[in] Event Event triggered.
+ @param[in] Context Parameter passed with the event.
+
+**/
+VOID
+CheckAllAPsStatus (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ UINTN CpuNumber;
+ UINTN NextCpuNumber;
+ CPU_DATA_BLOCK *CpuData;
+ CPU_DATA_BLOCK *NextCpuData;
+ EFI_STATUS Status;
+ CPU_STATE CpuState;
+
+ for (CpuNumber = 0; CpuNumber < mMPSystemData->NumberOfCpus; CpuNumber++) {
+ CpuData = &mMPSystemData->CpuData[CpuNumber];
+ if (CpuNumber == mMPSystemData->BSP) {
+ continue;
+ }
+
+ AsmAcquireMPLock (&CpuData->StateLock);
+ CpuState = CpuData->State;
+ AsmReleaseMPLock (&CpuData->StateLock);
+
+ switch (CpuState) {
+ case CPU_STATE_READY:
+ WakeUpAp (
+ CpuData,
+ mMPSystemData->Procedure,
+ mMPSystemData->ProcArguments
+ );
+ break;
+
+ case CPU_STATE_FINISHED:
+ if (mMPSystemData->SingleThread) {
+ Status = GetNextBlockedCpuNumber (&NextCpuNumber);
+ if (!EFI_ERROR (Status)) {
+ NextCpuData = &mMPSystemData->CpuData[NextCpuNumber];
+
+ AsmAcquireMPLock (&NextCpuData->ProcedureLock);
+ NextCpuData->State = CPU_STATE_READY;
+ AsmReleaseMPLock (&NextCpuData->ProcedureLock);
+
+ WakeUpAp (
+ NextCpuData,
+ mMPSystemData->Procedure,
+ mMPSystemData->ProcArguments
+ );
+ }
+ }
+
+ CpuData->State = CPU_STATE_IDLE;
+ mMPSystemData->FinishCount++;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ if (mMPSystemData->FinishCount == mMPSystemData->StartCount) {
+ gBS->SetTimer (
+ mMPSystemData->CheckAllAPsEvent,
+ TimerCancel,
+ 0
+ );
+ Status = gBS->SignalEvent (mMPSystemData->WaitEvent);
+ }
+
+ return ;
+}
+
+/**
+ @todo Add function description
+
+ @param[in] Event - @todo add argument description
+ @param[in] *Context - @todo add argument description
+
+**/
+VOID
+CheckThisAPStatus (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ CPU_DATA_BLOCK *CpuData;
+ EFI_STATUS Status;
+ CPU_STATE CpuState;
+
+ CpuData = &mMPSystemData->CpuData[mMPSystemData->StartedCpuNumber];
+
+ AsmAcquireMPLock (&CpuData->StateLock);
+ CpuState = CpuData->State;
+ AsmReleaseMPLock (&CpuData->StateLock);
+
+ if (CpuState == CPU_STATE_FINISHED) {
+ gBS->SetTimer (
+ mMPSystemData->CheckThisAPEvent,
+ TimerCancel,
+ 0
+ );
+ Status = gBS->SignalEvent (mMPSystemData->WaitEvent);
+ AsmAcquireMPLock (&CpuData->StateLock);
+ CpuData->State = CPU_STATE_IDLE;
+ AsmReleaseMPLock (&CpuData->StateLock);
+ }
+
+ return ;
+}
+
+/**
+ @todo Add function description
+
+ @param[in] TimeoutInMicroSecs - @todo add argument description
+
+ @retval - @todo add return values
+
+**/
+UINT64
+CalculateTimeout (
+ IN UINTN TimeoutInMicroSecs
+ )
+{
+ UINT64 CurrentTsc;
+ UINT64 ExpectedTsc;
+ UINT64 Frequency;
+ EFI_STATUS Status;
+
+ if (TimeoutInMicroSecs == 0) {
+ return 0xffffffffffff;
+ }
+
+ CurrentTsc = AsmReadTsc ();
+
+ Status = GetActualFrequency (mMetronome, &Frequency);
+
+ ExpectedTsc = CurrentTsc + MultU64x32 (Frequency, (UINT32)TimeoutInMicroSecs);
+
+ return ExpectedTsc;
+}
+
+/**
+ @todo Add function description
+
+ @param[in] ExpectedTsc - @todo add argument description
+
+ @retval - @todo add return values
+
+**/
+BOOLEAN
+CheckTimeout (
+ IN UINT64 ExpectedTsc
+ )
+{
+ UINT64 CurrentTsc;
+
+ CurrentTsc = AsmReadTsc ();
+ if (CurrentTsc >= ExpectedTsc) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ @todo Add function description
+
+ @param[out] NextCpuNumber - @todo add argument description
+
+ @retval EFI_SUCCESS - @todo Add description for return value
+ @retval EFI_NOT_FOUND - @todo Add description for return value
+
+**/
+EFI_STATUS
+GetNextBlockedCpuNumber (
+ OUT UINTN *NextCpuNumber
+ )
+{
+ UINTN CpuNumber;
+ CPU_STATE CpuState;
+ CPU_DATA_BLOCK *CpuData;
+
+ for (CpuNumber = 0; CpuNumber < mMPSystemData->NumberOfCpus; CpuNumber++) {
+ if (CpuNumber == mMPSystemData->BSP) {
+ continue;
+ }
+
+ CpuData = &mMPSystemData->CpuData[CpuNumber];
+
+ AsmAcquireMPLock (&CpuData->StateLock);
+ CpuState = CpuData->State;
+ AsmReleaseMPLock (&CpuData->StateLock);
+
+ if (CpuState == CPU_STATE_BLOCKED) {
+ *NextCpuNumber = CpuNumber;
+ return EFI_SUCCESS;
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+/**
+ Function to wake up a specified AP and assign procedure to it.
+
+ @param[in] CpuData CPU data block for the specified AP.
+ @param[in] Procedure Procedure to assign.
+ @param[in] ProcArguments Argument for Procedure.
+
+**/
+VOID
+WakeUpAp (
+ IN CPU_DATA_BLOCK *CpuData,
+ IN EFI_AP_PROCEDURE Procedure,
+ IN VOID *ProcArguments
+ )
+{
+ AsmAcquireMPLock (&CpuData->ProcedureLock);
+ CpuData->Parameter = ProcArguments;
+ CpuData->Procedure = Procedure;
+ AsmReleaseMPLock (&CpuData->ProcedureLock);
+
+ SendInterrupt (
+ BROADCAST_MODE_SPECIFY_CPU,
+ CpuData->ApicID,
+ 0,
+ DELIVERY_MODE_INIT,
+ TRIGGER_MODE_EDGE,
+ TRUE
+ );
+ SendInterrupt (
+ BROADCAST_MODE_SPECIFY_CPU,
+ CpuData->ApicID,
+ (UINT32) RShiftU64 (mAcpiCpuData->WakeUpBuffer, 12),
+ DELIVERY_MODE_SIPI,
+ TRIGGER_MODE_EDGE,
+ TRUE
+ );
+ CpuData->StateLock = 0;
+}
+
+/**
+ Check whether any AP is running for assigned task.
+
+ @retval TRUE - Some APs are running.
+ @retval FALSE - No AP is running.
+
+**/
+BOOLEAN
+ApRunning (
+ VOID
+ )
+{
+ CPU_DATA_BLOCK *CpuData;
+ UINTN CpuNumber;
+
+ for (CpuNumber = 0; CpuNumber < mMPSystemData->NumberOfCpus; CpuNumber++) {
+ CpuData = &mMPSystemData->CpuData[CpuNumber];
+
+ if (CpuNumber != mMPSystemData->BSP) {
+ if (CpuData->State == CPU_STATE_READY || CpuData->State == CPU_STATE_BUSY) {
+ return TRUE;
+ }
+ }
+ }
+
+ return FALSE;
+}
+
+/**
+ Count the number of APs that have been switched
+ to E0000 or F0000 segments by ReAllocateMemoryForAP().
+
+**/
+VOID
+LegacyRegionAPCount (
+ VOID
+ )
+{
+ AsmAcquireMPLock (&mMPSystemData->APSerializeLock);
+
+ mSwitchToLegacyRegionCount++;
+
+ AsmReleaseMPLock (&mMPSystemData->APSerializeLock);
+}
diff --git a/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/MtrrSync.c b/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/MtrrSync.c
new file mode 100644
index 0000000000..daf3f5dc60
--- /dev/null
+++ b/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/MtrrSync.c
@@ -0,0 +1,233 @@
+/** @file
+ Code which support multi-processor.
+
+ Copyright (c) 1999 - 2015, 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 "PlatformMpService.h"
+#include "MiscFuncs.h"
+#include "CpuRegs.h"
+
+extern MP_SYSTEM_DATA *mMPSystemData;
+
+EFI_MTRR_VALUES mFixedMtrrValues[] = {
+ { EFI_MSR_IA32_MTRR_FIX64K_00000, 0 },
+ { EFI_MSR_IA32_MTRR_FIX16K_80000, 0 },
+ { EFI_MSR_IA32_MTRR_FIX16K_A0000, 0 },
+ { EFI_MSR_IA32_MTRR_FIX4K_C0000, 0 },
+ { EFI_MSR_IA32_MTRR_FIX4K_C8000, 0 },
+ { EFI_MSR_IA32_MTRR_FIX4K_D0000, 0 },
+ { EFI_MSR_IA32_MTRR_FIX4K_D8000, 0 },
+ { EFI_MSR_IA32_MTRR_FIX4K_E0000, 0 },
+ { EFI_MSR_IA32_MTRR_FIX4K_E8000, 0 },
+ { EFI_MSR_IA32_MTRR_FIX4K_F0000, 0 },
+ { EFI_MSR_IA32_MTRR_FIX4K_F8000, 0 }
+};
+
+EFI_MTRR_VALUES mMtrrDefType[] = { { EFI_MSR_CACHE_IA32_MTRR_DEF_TYPE, 0 } };
+
+EFI_MTRR_VALUES mVariableMtrrValues[] = {
+ { EFI_MSR_CACHE_VARIABLE_MTRR_BASE, 0 },
+ { EFI_MSR_CACHE_VARIABLE_MTRR_BASE + 1, 0 },
+ { EFI_MSR_CACHE_VARIABLE_MTRR_BASE + 2, 0 },
+ { EFI_MSR_CACHE_VARIABLE_MTRR_BASE + 3, 0 },
+ { EFI_MSR_CACHE_VARIABLE_MTRR_BASE + 4, 0 },
+ { EFI_MSR_CACHE_VARIABLE_MTRR_BASE + 5, 0 },
+ { EFI_MSR_CACHE_VARIABLE_MTRR_BASE + 6, 0 },
+ { EFI_MSR_CACHE_VARIABLE_MTRR_BASE + 7, 0 },
+ { EFI_MSR_CACHE_VARIABLE_MTRR_BASE + 8, 0 },
+ { EFI_MSR_CACHE_VARIABLE_MTRR_BASE + 9, 0 },
+ { EFI_MSR_CACHE_VARIABLE_MTRR_BASE + 10, 0 },
+ { EFI_MSR_CACHE_VARIABLE_MTRR_BASE + 11, 0 },
+ { EFI_MSR_CACHE_VARIABLE_MTRR_BASE + 12, 0 },
+ { EFI_MSR_CACHE_VARIABLE_MTRR_BASE + 13, 0 },
+ { EFI_MSR_CACHE_VARIABLE_MTRR_BASE + 14, 0 },
+ { EFI_MSR_CACHE_VARIABLE_MTRR_END, 0 }
+};
+
+/**
+ Save the MTRR registers to global variables
+
+**/
+VOID
+ReadMtrrRegisters (
+ VOID
+ )
+{
+ UINT32 Index, IndexEnd;
+
+ //
+ // Read Fixed Mtrrs
+ //
+ for (Index = 0; Index < sizeof (mFixedMtrrValues) / sizeof (EFI_MTRR_VALUES); Index++) {
+ mFixedMtrrValues[Index].Value = AsmReadMsr64 (mFixedMtrrValues[Index].Index);
+ }
+
+ //
+ // Read def type Fixed Mtrrs
+ //
+ mMtrrDefType[0].Value = AsmReadMsr64 (EFI_MSR_CACHE_IA32_MTRR_DEF_TYPE);
+
+ //
+ // Read Variable Mtrr
+ //
+ IndexEnd = 2 * (UINT32)(AsmReadMsr64(EFI_MSR_IA32_MTRR_CAP) & B_EFI_MSR_IA32_MTRR_CAP_VARIABLE_SUPPORT);
+ for (Index = 0; Index < IndexEnd; Index++) {
+ if (Index < (sizeof (mVariableMtrrValues) / sizeof (EFI_MTRR_VALUES))) {
+ mVariableMtrrValues[Index].Value = AsmReadMsr64 (mVariableMtrrValues[Index].Index);
+ }
+ }
+
+ return ;
+}
+
+/**
+ Synch up the MTRR values for all processors
+
+ @param[in] Buffer - Not used.
+
+**/
+VOID
+EFIAPI
+MpMtrrSynchUp (
+ IN VOID *Buffer
+ )
+{
+ UINT32 Index, IndexEnd;
+ UINTN Cr4;
+ UINT64 MsrValue;
+ UINT64 ValidMtrrAddressMask;
+ EFI_CPUID_REGISTER FeatureInfo;
+ EFI_CPUID_REGISTER FunctionInfo;
+ UINT8 PhysicalAddressBits;
+
+ //
+ // ASM code to setup processor register before synching up the MTRRs
+ //
+ Cr4 = MpMtrrSynchUpEntry ();
+
+ //
+ // Get physical CPU MTRR width in case of difference from BSP
+ //
+ AsmCpuid (
+ EFI_CPUID_EXTENDED_FUNCTION,
+ &FunctionInfo.RegEax,
+ &FunctionInfo.RegEbx,
+ &FunctionInfo.RegEcx,
+ &FunctionInfo.RegEdx
+ );
+ PhysicalAddressBits = 36;
+ if (FunctionInfo.RegEax >= EFI_CPUID_VIRT_PHYS_ADDRESS_SIZE) {
+ AsmCpuid (
+ EFI_CPUID_VIRT_PHYS_ADDRESS_SIZE,
+ &FeatureInfo.RegEax,
+ &FeatureInfo.RegEbx,
+ &FeatureInfo.RegEcx,
+ &FeatureInfo.RegEdx
+ );
+ PhysicalAddressBits = (UINT8) FeatureInfo.RegEax;
+ }
+
+ ValidMtrrAddressMask = (LShiftU64( 1, PhysicalAddressBits) - 1) & 0xfffffffffffff000;
+
+ //
+ // Disable Fixed Mtrrs
+ //
+ AsmWriteMsr64 (EFI_MSR_CACHE_IA32_MTRR_DEF_TYPE, mMtrrDefType[0].Value & 0xFFFFF7FF);
+
+ //
+ // Update Fixed Mtrrs
+ //
+ for (Index = 0; Index < sizeof (mFixedMtrrValues) / sizeof (EFI_MTRR_VALUES); Index++) {
+ AsmWriteMsr64 (mFixedMtrrValues[Index].Index, mFixedMtrrValues[Index].Value);
+ }
+
+ //
+ // Synchup def type Fixed Mtrrs
+ //
+ AsmWriteMsr64 (EFI_MSR_CACHE_IA32_MTRR_DEF_TYPE, mMtrrDefType[0].Value);
+
+ //
+ // Synchup Base Variable Mtrr
+ //
+ IndexEnd = 2 * (UINT32)(AsmReadMsr64(EFI_MSR_IA32_MTRR_CAP) & B_EFI_MSR_IA32_MTRR_CAP_VARIABLE_SUPPORT);
+ for (Index = 0; Index < IndexEnd; Index += 2) {
+ if (Index < (sizeof (mVariableMtrrValues) / sizeof (EFI_MTRR_VALUES))) {
+ MsrValue = (mVariableMtrrValues[Index].Value & 0x0FFF) | (mVariableMtrrValues[Index].Value & ValidMtrrAddressMask);
+ AsmWriteMsr64 (mVariableMtrrValues[Index].Index, MsrValue);
+ }
+ }
+
+ //
+ // Synchup Mask Variable Mtrr including valid bit
+ //
+ for (Index = 1; Index < IndexEnd; Index += 2) {
+ if (Index < (sizeof (mVariableMtrrValues) / sizeof (EFI_MTRR_VALUES))) {
+ MsrValue = (mVariableMtrrValues[Index].Value & 0x0FFF) | (mVariableMtrrValues[Index].Value & ValidMtrrAddressMask);
+ AsmWriteMsr64 (mVariableMtrrValues[Index].Index, MsrValue);
+ }
+ }
+
+ //
+ // ASM code to setup processor register after synching up the MTRRs
+ //
+ MpMtrrSynchUpExit (Cr4);
+}
+
+/**
+ @todo add description
+
+**/
+VOID
+SaveBspMtrrForS3 (
+ )
+{
+ UINTN Index, IndexEnd;
+ UINTN TableIndex;
+
+ TableIndex = 0;
+
+ for (Index = 0; Index < sizeof (mFixedMtrrValues) / sizeof (mFixedMtrrValues[0]); Index++) {
+ mMPSystemData->S3BspMtrrTable[TableIndex].Index = mFixedMtrrValues[Index].Index;
+ mMPSystemData->S3BspMtrrTable[TableIndex].Value = mFixedMtrrValues[Index].Value;
+ TableIndex++;
+ }
+
+ IndexEnd = 2 * (UINT32)(AsmReadMsr64(EFI_MSR_IA32_MTRR_CAP) & B_EFI_MSR_IA32_MTRR_CAP_VARIABLE_SUPPORT);
+ for (Index = 0; Index < IndexEnd; Index ++) {
+ if (TableIndex < (sizeof (mMPSystemData->S3BspMtrrTable) / sizeof (mMPSystemData->S3BspMtrrTable[0]))) {
+ if (Index < (sizeof (mVariableMtrrValues) / sizeof (mVariableMtrrValues[0]))) {
+ mMPSystemData->S3BspMtrrTable[TableIndex].Index = mVariableMtrrValues[Index].Index;
+ mMPSystemData->S3BspMtrrTable[TableIndex].Value = mVariableMtrrValues[Index].Value;
+ TableIndex++;
+ }
+ }
+ }
+
+ if( TableIndex < ( (sizeof(mMPSystemData->S3BspMtrrTable) / sizeof(mMPSystemData->S3BspMtrrTable[0]) - 2) )) {
+ mMPSystemData->S3BspMtrrTable[TableIndex].Index = mMtrrDefType[0].Index;
+ mMPSystemData->S3BspMtrrTable[TableIndex].Value = mMtrrDefType[0].Value;
+ TableIndex++;
+
+ //
+ // To terminate the table during S3 resume for MTRR synch up
+ //
+ mMPSystemData->S3BspMtrrTable[TableIndex].Index = 0;
+ } else if( TableIndex < ( (sizeof(mMPSystemData->S3BspMtrrTable) / sizeof(mMPSystemData->S3BspMtrrTable[0]) - 1) )) {
+ //
+ // To terminate the table during S3 resume for MTRR synch up
+ //
+ mMPSystemData->S3BspMtrrTable[TableIndex].Index = 0;
+ }
+
+ ASSERT (TableIndex < MAX_CPU_S3_MTRR_ENTRY);
+}
diff --git a/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/PlatformMpService.h b/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/PlatformMpService.h
new file mode 100644
index 0000000000..aaac6ceb8a
--- /dev/null
+++ b/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/PlatformMpService.h
@@ -0,0 +1,636 @@
+/** @file
+ some definitions for MP services Protocol.
+
+ Copyright (c) 1999 - 2015, 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 _PLATFORM_MP_SERVICE_H_
+#define _PLATFORM_MP_SERVICE_H_
+
+#include "CpuDxe.h"
+#include "MpCommon.h"
+
+/**
+ @todo add description
+
+**/
+typedef struct {
+ UINT32 Package;
+ UINT32 Die;
+ UINT32 Core;
+ UINT32 Thread;
+} PHYSICAL_LOCATION;
+
+//
+// Constant definitions
+//
+#define FOURGB 0x100000000
+#define ONEPAGE 0x1000
+
+#define RENDEZVOUS_PROC_LENGTH 0x1000
+#define STACK_SIZE_PER_PROC 0x8000
+#define MAX_CPU_S3_MTRR_ENTRY 0x0020
+#define MAX_CPU_S3_TABLE_SIZE 0x0400
+
+#define AP_HALT_CODE_SIZE 10
+
+#define CPU_CHECK_AP_INTERVAL 0x10 // microseconds
+//
+// The MP data structure follows.
+//
+#define CPU_SWITCH_STATE_IDLE 0
+#define CPU_SWITCH_STATE_STORED 1
+#define CPU_SWITCH_STATE_LOADED 2
+
+#define MSR_L3_CACHE_DISABLE 0x40
+
+/**
+ @todo add description
+
+**/
+typedef struct {
+ UINT8 Lock; // offset 0
+ UINT8 State; // offset 1
+ UINTN StackPointer; // offset 4 / 8
+ IA32_DESCRIPTOR Gdtr; // offset 8 / 16
+ IA32_DESCRIPTOR Idtr; // offset 14 / 26
+} CPU_EXCHANGE_ROLE_INFO;
+
+/**
+ MTRR table definitions
+**/
+typedef struct {
+ UINT16 Index;
+ UINT64 Value;
+} EFI_MTRR_VALUES;
+
+typedef enum {
+ CPU_STATE_IDLE,
+ CPU_STATE_BLOCKED,
+ CPU_STATE_READY,
+ CPU_STATE_BUSY,
+ CPU_STATE_FINISHED,
+ CPU_STATE_DISABLED
+} CPU_STATE;
+
+//
+// Define CPU feature information
+//
+#define MAX_FEATURE_NUM 6
+
+/**
+ @todo add description
+
+**/
+typedef struct {
+ UINTN Index;
+ UINT32 ApicId;
+ UINT32 Version;
+ UINT32 FeatureDelta;
+ UINT32 Features[MAX_FEATURE_NUM];
+} LEAST_FEATURE_PROC;
+
+/**
+// Define Individual Processor Data block.
+**/
+typedef struct {
+ UINT32 ApicID;
+ EFI_AP_PROCEDURE Procedure;
+ VOID *Parameter;
+ UINT8 StateLock;
+ UINT8 ProcedureLock;
+ UINT32 Health;
+ BOOLEAN SecondaryCpu;
+ UINTN NumberOfCores;
+ UINTN NumberOfThreads;
+ UINT64 ActualFsbFrequency;
+ EFI_STATUS MicrocodeStatus;
+ UINT32 FailedRevision;
+ EFI_CPU_PHYSICAL_LOCATION PhysicalLocation;
+ CPU_STATE State;
+ //
+ // for PI MP Services Protocol
+ //
+ BOOLEAN *Finished;
+ UINT64 ExpectedTime;
+ EFI_EVENT WaitEvent;
+ EFI_EVENT CheckThisAPEvent;
+} CPU_DATA_BLOCK;
+
+/**
+ @todo add description
+
+**/
+typedef struct {
+ UINT32 ApicId;
+ UINT32 MsrIndex;
+ UINT64 MsrValue;
+} MP_CPU_S3_SCRIPT_DATA;
+
+/**
+ @todo add description
+
+**/
+typedef struct {
+ UINT32 S3BootScriptTable;
+ UINT32 S3BspMtrrTable;
+ UINT32 VirtualWireMode;
+} MP_CPU_S3_DATA_POINTER;
+
+/**
+ @todo add description
+
+**/
+#pragma pack (1)
+typedef struct {
+ UINT32 ApicId;
+ UINT32 Health;
+} BIST_HOB_DATA;
+#pragma pack ()
+
+/**
+ Define MP data block which consumes individual processor block.
+**/
+typedef struct {
+ UINT8 APSerializeLock;
+
+ UINT8 Tm2Core2BusRatio; // for thermal monitor 2 initialization
+ UINT8 Tm2Vid; // for thermal monitor 2 initialization
+ BOOLEAN LimitCpuidMaximumValue; // make processor look like < F40
+ BOOLEAN EnableL3Cache;
+ BOOLEAN IsC1eSupported;
+ BOOLEAN C1eEnable;
+ BOOLEAN AesEnable;
+ BOOLEAN PeciEnable;
+ BOOLEAN ProcessorVmxEnable;
+ BOOLEAN ProcessorBistEnable;
+ BOOLEAN ProcessorMsrLockControl;
+ BOOLEAN Processor3StrikeControl;
+ BOOLEAN LtEnable;
+ BOOLEAN EchoTprDisable;
+ BOOLEAN MonitorMwaitEnable;
+ BOOLEAN FastString;
+ BOOLEAN TurboModeEnable;
+ BOOLEAN ExtremeEnable;
+ BOOLEAN XapicEnable;
+ BOOLEAN MachineCheckEnable;
+ BOOLEAN MLCSpatialPrefetcherEnable;
+ BOOLEAN MLCStreamerPrefetcherEnable;
+ BOOLEAN DCUStreamerPrefetcherEnable;
+ BOOLEAN DCUIPPrefetcherEnable;
+ BOOLEAN CcxEnable;
+ BOOLEAN C1AutoDemotion;
+ BOOLEAN C3AutoDemotion;
+ BOOLEAN Vr11Enable;
+ UINT8 PackageCState;
+
+ BOOLEAN Gv3Enable;
+ BOOLEAN PsdState;
+ BOOLEAN EnableSecondaryCpu;
+ BOOLEAN DcaEnable;
+ UINTN DcaPrefetchDelayValue;
+
+ BOOLEAN DCUModeSelection;
+ BOOLEAN BiDirectionalProchot;
+
+ UINTN NumberOfCpus;
+ UINTN MaximumCpusForThisSystem;
+
+ CPU_EXCHANGE_ROLE_INFO BSPInfo;
+ CPU_EXCHANGE_ROLE_INFO APInfo;
+
+ EFI_CPU_ARCH_PROTOCOL *CpuArch;
+ EFI_EVENT CheckThisAPEvent;
+ EFI_EVENT CheckAllAPsEvent;
+ EFI_EVENT WaitEvent;
+ UINTN BSP;
+ BIST_HOB_DATA *BistHobData;
+ UINTN BistHobSize;
+
+ UINTN FinishCount;
+ UINTN StartCount;
+ EFI_AP_PROCEDURE Procedure;
+ VOID *ProcArguments;
+ BOOLEAN SingleThread;
+ UINTN StartedCpuNumber;
+ UINT8 Pad;
+
+ CPU_DATA_BLOCK CpuData[MAXIMUM_CPU_NUMBER];
+ EFI_CPU_STATE_CHANGE_CAUSE DisableCause[MAXIMUM_CPU_NUMBER];
+
+ UINT8 S3BootScriptLock;
+ UINT32 S3BootScriptCount;
+ MP_CPU_S3_DATA_POINTER S3DataPointer;
+ MP_CPU_S3_SCRIPT_DATA S3BootScriptTable[MAX_CPU_S3_TABLE_SIZE];
+ EFI_MTRR_VALUES S3BspMtrrTable[MAX_CPU_S3_MTRR_ENTRY];
+ UINT8 ActiveProcessorCores;
+} MP_SYSTEM_DATA;
+
+#pragma pack (1)
+
+/**
+ @todo add description
+
+**/
+typedef struct {
+ ACPI_CPU_DATA_COMPATIBILITY AcpiCpuData;
+ MP_SYSTEM_DATA MPSystemData;
+ IA32_DESCRIPTOR GdtrProfile;
+ IA32_DESCRIPTOR IdtrProfile;
+ EFI_CPU_MICROCODE_HEADER* MicrocodePointerBuffer[NUMBER_OF_MICROCODE_UPDATE + 1];
+} MP_CPU_RESERVED_DATA;
+
+#define CPU_MP_SERVICE_PRIVATE_SIGNATURE EFI_SIGNATURE_32 ('m', 'p', '3', '2')
+
+/**
+ @todo add description
+
+**/
+typedef struct {
+ UINTN Signature;
+ EFI_HANDLE Handle;
+ EFI_MP_SERVICES_PROTOCOL MpService;
+ MP_SYSTEM_DATA MPSystemData;
+} CPU_MP_SERVICE_PROTOCOL_PRIVATE;
+
+#define CPU_MP_SERVICE_PRIVATE_DATA_FROM_THIS(a) \
+ CR (a, \
+ CPU_MP_SERVICE_PROTOCOL_PRIVATE, \
+ MpService, \
+ CPU_MP_SERVICE_PRIVATE_SIGNATURE \
+ )
+#pragma pack ()
+
+extern CPU_MP_SERVICE_PROTOCOL_PRIVATE *Private;
+extern MP_SYSTEM_DATA *mMPSystemData;
+extern ACPI_CPU_DATA_COMPATIBILITY *mAcpiCpuData;
+
+//
+// Prototypes.
+//
+EFI_STATUS
+MpInitialize (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+;
+
+/**
+ Implementation of GetNumberOfProcessors() service of MP Services Protocol.
+
+ This service retrieves the number of logical processor in the platform
+ and the number of those logical processors that are enabled on this boot.
+ This service may only be called from the BSP.
+
+ @param[in] This A pointer to the EFI_MP_SERVICES_PROTOCOL instance.
+ @param[in] NumberOfProcessors Pointer to the total number of logical processors in the system,
+ including the BSP and disabled APs.
+ @param[in] NumberOfEnabledProcessors Pointer to the number of enabled logical processors that exist
+ in system, including the BSP.
+
+ @retval EFI_SUCCESS Number of logical processors and enabled logical processors retrieved..
+ @retval EFI_DEVICE_ERROR Caller processor is AP.
+ @retval EFI_INVALID_PARAMETER NumberOfProcessors is NULL.
+ @retval EFI_INVALID_PARAMETER NumberOfEnabledProcessors is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+GetNumberOfProcessors (
+ IN EFI_MP_SERVICES_PROTOCOL *This,
+ OUT UINTN *NumberOfProcessors,
+ OUT UINTN *NumberOfEnabledProcessors
+ );
+
+/**
+ Implementation of GetProcessorInfo() service of MP Services Protocol.
+
+ Gets detailed MP-related information on the requested processor at the
+ instant this call is made. This service may only be called from the BSP.
+
+ @param[in] This A pointer to the EFI_MP_SERVICES_PROTOCOL instance.
+ @param[in] ProcessorNumber The handle number of processor.
+ @param[in] ProcessorInfoBuffer A pointer to the buffer where information for the requested processor is deposited.
+
+ @retval EFI_SUCCESS Processor information successfully returned.
+ @retval EFI_DEVICE_ERROR Caller processor is AP.
+ @retval EFI_INVALID_PARAMETER ProcessorInfoBuffer is NULL
+ @retval EFI_NOT_FOUND Processor with the handle specified by ProcessorNumber does not exist.
+
+**/
+EFI_STATUS
+EFIAPI
+GetProcessorInfo (
+ IN EFI_MP_SERVICES_PROTOCOL *This,
+ IN UINTN ProcessorNumber,
+ OUT EFI_PROCESSOR_INFORMATION *ProcessorInfoBuffer
+ );
+
+/**
+ MP Service to get specified application processor (AP)
+ to execute a caller-provided code stream.
+
+ @param[in] This Pointer to MP Service Protocol
+ @param[in] Procedure The procedure to be assigned to AP.
+ @param[in] ProcessorNumber The handle number of processor.
+ @param[in] WaitEvent If timeout, the event to be triggered after this AP finishes.
+ @param[in] TimeoutInMicroSecs The timeout value in microsecond. Zero means infinity.
+ @param[in] ProcArguments Argument for Procedure.
+
+ @retval EFI_INVALID_PARAMETER Procudure is NULL.
+ @retval EFI_INVALID_PARAMETER Number of CPU out of range, or it belongs to BSP.
+ @retval EFI_INVALID_PARAMETER Specified CPU is not idle.
+ @retval EFI_SUCCESS The AP has finished.
+ @retval EFI_TIMEOUT Time goes out before the AP has finished.
+
+**/
+EFI_STATUS
+EFIAPI
+StartupThisAP (
+ IN EFI_MP_SERVICES_PROTOCOL *This,
+ IN EFI_AP_PROCEDURE Procedure,
+ IN UINTN ProcessorNumber,
+ IN EFI_EVENT WaitEvent OPTIONAL,
+ IN UINTN TimeoutInMicroSecs OPTIONAL,
+ IN VOID *ProcArguments OPTIONAL,
+ OUT BOOLEAN *Finished OPTIONAL
+ );
+
+/**
+ MP Service to get all the available application processors (APs)
+ to execute a caller-provided code stream.
+
+ @param[in] This Pointer to MP Service Protocol
+ @param[in] Procedure The procedure to be assigned to APs.
+ @param[in] SingleThread If true, all APs execute in block mode.
+ Otherwise, all APs exceute in non-block mode.
+ @param[in] WaitEvent If timeout, the event to be triggered after all APs finish.
+ @param[in] TimeoutInMicroSecs The timeout value in microsecond. Zero means infinity.
+ @param[in] ProcArguments Argument for Procedure.
+ @param[in] FailedCPUList If not NULL, all APs that fail to start will be recorded in the list.
+
+ @retval EFI_INVALID_PARAMETER Procudure is NULL.
+ @retval EFI_SUCCESS Only 1 logical processor exists.
+ @retval EFI_SUCCESS All APs have finished.
+ @retval EFI_TIMEOUT Time goes out before all APs have finished.
+
+**/
+EFI_STATUS
+EFIAPI
+StartupAllAPs (
+ IN EFI_MP_SERVICES_PROTOCOL *This,
+ IN EFI_AP_PROCEDURE Procedure,
+ IN BOOLEAN SingleThread,
+ IN EFI_EVENT WaitEvent OPTIONAL,
+ IN UINTN TimeoutInMicroSecs,
+ IN VOID *ProcArguments OPTIONAL,
+ OUT UINTN **FailedCPUList OPTIONAL
+ );
+
+/**
+ MP Service to makes the current BSP into an AP and then switches the
+ designated AP into the AP. This procedure is usually called after a CPU
+ test that has found that BSP is not healthy to continue it's responsbilities.
+
+ @param[in] This Pointer to MP Service Protocol.
+ @param[in] ProcessorNumber The handle number of processor.
+ @param[in] EnableOldBSPState Whether to enable or disable the original BSP.
+
+ @retval EFI_INVALID_PARAMETER Number for Specified AP out of range.
+ @retval EFI_INVALID_PARAMETER Number of specified CPU belongs to BSP.
+ @retval EFI_NOT_READY Specified AP is not idle.
+ @retval EFI_SUCCESS BSP successfully switched.
+
+**/
+EFI_STATUS
+EFIAPI
+SwitchBSP (
+ IN EFI_MP_SERVICES_PROTOCOL *This,
+ IN UINTN ProcessorNumber,
+ IN BOOLEAN EnableOldBSPState
+ );
+
+/**
+ Implementation of EnableDisableAP() service of MP Services Protocol.
+
+ This service lets the caller enable or disable an AP.
+ This service may only be called from the BSP.
+
+ @param[in] This A pointer to the EFI_MP_SERVICES_PROTOCOL instance.
+ @param[in] ProcessorNumber The handle number of processor.
+ @param[in] NewAPState Indicates whether the newstate of the AP is enabled or disabled.
+ @param[in] HealthState Indicates new health state of the AP..
+
+ @retval EFI_SUCCESS AP successfully enabled or disabled.
+ @retval EFI_DEVICE_ERROR Caller processor is AP.
+ @retval EFI_NOT_FOUND Processor with the handle specified by ProcessorNumber does not exist.
+ @retval EFI_INVALID_PARAMETERS ProcessorNumber specifies the BSP.
+
+**/
+EFI_STATUS
+EFIAPI
+EnableDisableAP (
+ IN EFI_MP_SERVICES_PROTOCOL *This,
+ IN UINTN ProcessorNumber,
+ IN BOOLEAN NewAPState,
+ IN UINT32 *HealthState OPTIONAL
+ );
+
+EFI_STATUS
+EFIAPI
+WhoAmI (
+ IN EFI_MP_SERVICES_PROTOCOL *This,
+ OUT UINTN *CpuNumber
+ );
+
+EFI_STATUS
+GetMPDataBlocks (
+ IN MP_SYSTEM_DATA *MPSystemData
+ );
+
+EFI_STATUS
+InitializeMpSystemData (
+ VOID
+ );
+
+//
+// Assembly stub definitions.
+//
+VOID
+AsmGetProcsParams1 (
+ OUT UINTN MyGlobalID,
+ OUT UINTN MyNumberOfProcessorCores,
+ OUT UINTN MyNumberOfProcessorThreads,
+ OUT UINTN RendezIntNumber
+ );
+
+VOID
+AsmGetProcsParams2 (
+ OUT UINTN MyHealthStatus,
+ OUT UINTN MyNodeNumber,
+ OUT UINTN MyNodeMemSize,
+ OUT UINTN MyProcessorCompatibility
+ );
+
+VOID
+AsmGetProcsParams3 (
+ OUT UINTN MyProcessorTestMask,
+ OUT UINTN MyProcessorSlotNumber,
+ OUT UINTN MyProcessorPackageNumber
+ );
+
+VOID
+AsmFlushProgData (
+ IN UINTN MemAddress,
+ IN UINTN Count
+ );
+
+VOID
+AsmWakeUpAPs (
+ IN UINTN *WakeUpBuffer,
+ IN UINTN MemAddress,
+ IN UINTN *StackAddressStart,
+ IN UINTN StackSize,
+ IN UINTN *APDoneSemaphore,
+ IN UINTN *GDTPageAddress
+ );
+
+EFI_STATUS
+WakeUpAPs (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+VOID
+AsmExchangeRole (
+ IN CPU_EXCHANGE_ROLE_INFO *MyInfo,
+ IN CPU_EXCHANGE_ROLE_INFO *OthersInfo
+ );
+
+VOID
+FutureBSPProc (
+ IN MP_SYSTEM_DATA *MPSystemData
+ );
+
+EFI_STATUS
+GetMpBistStatus (
+ IN MP_SYSTEM_DATA *MPSystemData
+ );
+
+//
+// Function declarations
+//
+VOID
+InitializeMpData (
+ IN UINTN ProcessorInstance
+ );
+
+VOID
+EFIAPI
+MpServiceInitialize (
+ VOID
+ );
+
+UINTN
+MpMtrrSynchUpEntry (
+ VOID
+ );
+
+VOID
+MpMtrrSynchUpExit (
+ UINTN Cr4
+ );
+
+VOID
+SaveBspMtrrForS3 (
+ );
+
+EFI_STATUS
+FillInProcessorInformation (
+ IN MP_SYSTEM_DATA *MPSystemData,
+ IN BOOLEAN BSP,
+ IN UINT32 BistParam
+ );
+
+VOID
+APFinishTask (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+EFI_STATUS
+SetApicBSPBit (
+ IN BOOLEAN Enable
+ );
+
+EFI_STATUS
+ChangeCpuState (
+ IN UINTN CpuNumber,
+ IN BOOLEAN NewState,
+ IN EFI_CPU_STATE_CHANGE_CAUSE Cause
+ );
+
+BOOLEAN
+IsSecondaryThread (
+ VOID
+ );
+
+VOID
+CheckAllAPsStatus (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+VOID
+CheckThisAPStatus (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+UINT64
+CalculateTimeout (
+ IN UINTN TimeoutInMicroSecs
+ );
+
+BOOLEAN
+CheckTimeout (
+ IN UINT64 ExpectedTsc
+ );
+
+EFI_STATUS
+GetNextBlockedCpuNumber (
+ OUT UINTN *NextCpuNumber
+ );
+
+EFI_STATUS
+FillInCpuLocation (
+ IN EFI_CPU_PHYSICAL_LOCATION *Location
+ );
+
+VOID
+DetailedInitialization (
+ VOID
+ );
+
+VOID
+WakeUpAp (
+ IN CPU_DATA_BLOCK *CpuData,
+ IN EFI_AP_PROCEDURE Procedure,
+ IN VOID *Parameter
+ );
+
+UINT8
+GetCoreNumber (
+ VOID
+ );
+
+#endif
diff --git a/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/x64/Cpu.asm b/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/x64/Cpu.asm
new file mode 100644
index 0000000000..c621e28bfb
--- /dev/null
+++ b/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/x64/Cpu.asm
@@ -0,0 +1,199 @@
+;; @file
+; Assembly code for the IA-32 resources.
+;
+; Copyright (c) 2005 - 2015, 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.
+;
+;;
+
+text SEGMENT
+
+
+
+
+;------------------------------------------------------------------------------
+; UINTN
+; CpuReadCr0 (
+; VOID
+; )
+;------------------------------------------------------------------------------
+CpuReadCr0 PROC PUBLIC
+ mov rax, cr0
+ ret
+CpuReadCr0 ENDP
+
+;------------------------------------------------------------------------------
+; VOID
+; CpuWriteCr0 (
+; UINTN Value
+; )
+;------------------------------------------------------------------------------
+CpuWriteCr0 PROC PUBLIC
+ mov cr0, rcx
+ ret
+CpuWriteCr0 ENDP
+
+;------------------------------------------------------------------------------
+; UINTN
+; CpuReadCr3 (
+; VOID
+; )
+;------------------------------------------------------------------------------
+CpuReadCr3 PROC PUBLIC
+ mov rax, cr3
+ ret
+CpuReadCr3 ENDP
+
+;------------------------------------------------------------------------------
+; UINTN
+; CpuWriteCr3 (
+; VOID
+; )
+;------------------------------------------------------------------------------
+CpuWriteCr3 PROC PUBLIC
+ mov cr3, rcx
+ ret
+CpuWriteCr3 ENDP
+
+
+;------------------------------------------------------------------------------
+; UINTN
+; CpuFlushTlb (
+; VOID
+; )
+;------------------------------------------------------------------------------
+CpuFlushTlb PROC PUBLIC
+ mov rax, cr3
+ mov cr3, rax
+ ret
+CpuFlushTlb ENDP
+
+
+;------------------------------------------------------------------------------
+; UINTN
+; CpuSetPower2 (
+; IN UINTN Input
+; );
+;------------------------------------------------------------------------------
+CpuSetPower2 PROC PUBLIC
+ bsr rdx, rcx
+ bts rax, rdx
+ ret
+CpuSetPower2 ENDP
+
+;------------------------------------------------------------------------------
+; UINT64
+; CpuReadTsc (
+; VOID
+; );
+;------------------------------------------------------------------------------
+CpuReadTsc PROC PUBLIC
+ rdtsc
+ ret
+CpuReadTsc ENDP
+
+;------------------------------------------------------------------------------
+; UINT64
+; CpuSwitchStacks (
+; IN UINTN EntryPoint, // rcx
+; IN UINTN Parameter1, // rdx
+; IN UINTN NewStack, // r8
+; IN UINTN NewBsp // r9 - Only used on IPF
+; );
+;------------------------------------------------------------------------------
+CpuSwitchStacks PROC PUBLIC
+ mov rsp, r8 ; rsp = NewStack
+ push rdx ; Parameter1
+ call rcx ; rcx = EntryPoint
+ ;
+ ; no ret as we have a new stack and we jumped to the new location
+ ;
+CpuSwitchStacks ENDP
+
+;------------------------------------------------------------------------------
+; UINT64
+; CpuSwitchStacks2Args (
+; IN UINTN EntryPoint, // rcx
+; IN UINTN Parameter1, // rdx
+; IN UINTN Parameter2, // r8
+; IN UINTN NewStack, // r9
+; IN UINTN Bsp // Only used on IPF
+; );
+;
+; BSP not used on IA-32
+;
+;------------------------------------------------------------------------------
+CpuSwitchStacks2Args PROC PUBLIC
+ mov rsp, r8 ; rsp = NewStack
+ push r8 ; Parameter2
+ push rdx ; Parameter1
+ call rcx ; rcx = EntryPoint
+ ;
+ ; no ret as we have a new stack and we jumped to the new location
+ ;
+ CpuSwitchStacks2Args ENDP
+
+
+;------------------------------------------------------------------------------
+; UINT16
+; CpuCodeSegment (
+; VOID
+; );
+;------------------------------------------------------------------------------
+CpuCodeSegment PROC PUBLIC
+ xor eax, eax
+ mov eax, cs
+ ret
+CpuCodeSegment ENDP
+
+
+;------------------------------------------------------------------------------
+; VOID
+; CpuBreak (
+; VOID
+; );
+;------------------------------------------------------------------------------
+CpuBreak PROC PUBLIC
+ int 3
+ ret
+CpuBreak ENDP
+
+
+;------------------------------------------------------------------------------
+; VOID
+; CpuLoadGlobalDescriptorTable (
+; VOID *Table16ByteAligned
+; );
+;------------------------------------------------------------------------------
+CpuLoadGlobalDescriptorTable PROC PUBLIC
+ lgdt FWORD PTR [rcx]
+ ret
+CpuLoadGlobalDescriptorTable ENDP
+
+CpuInitSelectors PROC PUBLIC
+ int 68h
+ ret
+CpuInitSelectors ENDP
+;------------------------------------------------------------------------------
+; VOID
+; CpuLoadInterruptDescriptorTable (
+; VOID *Table16ByteAligned
+; );
+;------------------------------------------------------------------------------
+CpuLoadInterruptDescriptorTable PROC PUBLIC
+ lidt FWORD PTR [rcx]
+ ret
+CpuLoadInterruptDescriptorTable ENDP
+
+
+text ENDS
+END
+
+
diff --git a/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/x64/CpuAsm.asm b/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/x64/CpuAsm.asm
new file mode 100644
index 0000000000..1082001fc4
--- /dev/null
+++ b/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/x64/CpuAsm.asm
@@ -0,0 +1,462 @@
+;; @file
+; Assembly code of the implementation of X64 CPU architectural protocol
+;
+; Copyright (c) 2005 - 2015, 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.
+;
+;;
+
+
+.code
+
+EXTRN mErrorCodeFlag:DWORD ; Error code flags for exceptions
+
+ExternalVectorTablePtr QWORD 0 ; point to the external interrupt vector table
+
+InitializeExternalVectorTablePtr PROC PUBLIC
+ mov ExternalVectorTablePtr, rcx
+ ret
+InitializeExternalVectorTablePtr ENDP
+;
+;
+;
+;------------------------------------------------------------------------------
+; Generic IDT Vector Handlers for the Host. They are all the same so they
+; will compress really well.
+;
+; By knowing the return address for Vector 00 you can can calculate the
+; vector number by looking at the call CommonInterruptEntry return address.
+; (return address - (AsmIdtVector00 + 5))/8 == IDT index
+;
+;------------------------------------------------------------------------------
+
+ALIGN 8
+
+PUBLIC AsmIdtVector00
+
+AsmIdtVector00 LABEL BYTE
+REPEAT 256
+ call CommonInterruptEntry
+ dw ( $ - AsmIdtVector00 - 5 ) / 8 ; vector number
+ nop
+ENDM
+
+
+;---------------------------------------;
+; CommonInterruptEntry ;
+;---------------------------------------;
+; The follow algorithm is used for the common interrupt routine.
+
+;
+; +---------------------+ <-- 16-byte aligned ensured by processor
+; + Old SS +
+; +---------------------+
+; + Old RSP +
+; +---------------------+
+; + RFlags +
+; +---------------------+
+; + CS +
+; +---------------------+
+; + RIP +
+; +---------------------+
+; + Error Code +
+; +---------------------+
+; + RCX / Vector Number +
+; +---------------------+
+; + RBP +
+; +---------------------+ <-- RBP, 16-byte aligned
+;
+
+CommonInterruptEntry PROC PUBLIC
+ cli
+ ;
+ ; All interrupt handlers are invoked through interrupt gates, so
+ ; IF flag automatically cleared at the entry point
+ ;
+ ;
+ ; Calculate vector number
+ ;
+ xchg rcx, [rsp] ; get the return address of call, actually, it is the address of vector number.
+ movzx ecx, word ptr [rcx]
+ cmp ecx, 32 ; Intel reserved vector for exceptions?
+ jae NoErrorCode
+ bt mErrorCodeFlag, ecx
+ jc @F
+
+NoErrorCode:
+ ;
+ ; Push a dummy error code on the stack
+ ; to maintain coherent stack map
+ ;
+ push [rsp]
+ mov qword ptr [rsp + 8], 0
+@@:
+ push rbp
+ mov rbp, rsp
+
+ ;
+ ; Since here the stack pointer is 16-byte aligned, so
+ ; EFI_FX_SAVE_STATE_X64 of EFI_SYSTEM_CONTEXT_x64
+ ; is 16-byte aligned
+ ;
+
+;; UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;
+;; UINT64 R8, R9, R10, R11, R12, R13, R14, R15;
+ push r15
+ push r14
+ push r13
+ push r12
+ push r11
+ push r10
+ push r9
+ push r8
+ push rax
+ push qword ptr [rbp + 8] ; RCX
+ push rdx
+ push rbx
+ push qword ptr [rbp + 48] ; RSP
+ push qword ptr [rbp] ; RBP
+ push rsi
+ push rdi
+
+;; UINT64 Gs, Fs, Es, Ds, Cs, Ss; insure high 16 bits of each is zero
+ movzx rax, word ptr [rbp + 56]
+ push rax ; for ss
+ movzx rax, word ptr [rbp + 32]
+ push rax ; for cs
+ mov rax, ds
+ push rax
+ mov rax, es
+ push rax
+ mov rax, fs
+ push rax
+ mov rax, gs
+ push rax
+
+ mov [rbp + 8], rcx ; save vector number
+
+;; UINT64 Rip;
+ push qword ptr [rbp + 24]
+
+;; UINT64 Gdtr[2], Idtr[2];
+ sub rsp, 16
+ sidt fword ptr [rsp]
+ sub rsp, 16
+ sgdt fword ptr [rsp]
+
+;; UINT64 Ldtr, Tr;
+ xor rax, rax
+ str ax
+ push rax
+ sldt ax
+ push rax
+
+;; UINT64 RFlags;
+ push qword ptr [rbp + 40]
+
+;; UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;
+ mov rax, cr8
+ push rax
+ mov rax, cr4
+ or rax, 208h
+ mov cr4, rax
+ push rax
+ mov rax, cr3
+ push rax
+ mov rax, cr2
+ push rax
+ xor rax, rax
+ push rax
+ mov rax, cr0
+ push rax
+
+;; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
+ mov rax, dr7
+ push rax
+;; clear Dr7 while executing debugger itself
+ xor rax, rax
+ mov dr7, rax
+
+ mov rax, dr6
+ push rax
+;; insure all status bits in dr6 are clear...
+ xor rax, rax
+ mov dr6, rax
+
+ mov rax, dr3
+ push rax
+ mov rax, dr2
+ push rax
+ mov rax, dr1
+ push rax
+ mov rax, dr0
+ push rax
+
+;; FX_SAVE_STATE_X64 FxSaveState;
+
+ sub rsp, 512
+ mov rdi, rsp
+ db 0fh, 0aeh, 00000111y ;fxsave [rdi]
+
+;; UINT32 ExceptionData;
+ push qword ptr [rbp + 16]
+
+;; call into exception handler
+ mov rcx, [rbp + 8]
+ mov rax, ExternalVectorTablePtr ; get the interrupt vectors base
+ mov rax, [rax + rcx * 8]
+ or rax, rax ; NULL?
+
+ je nonNullValue;
+
+;; Prepare parameter and call
+; mov rcx, [rbp + 8]
+ mov rdx, rsp
+ ;
+ ; Per X64 calling convention, allocate maximum parameter stack space
+ ; and make sure RSP is 16-byte aligned
+ ;
+ sub rsp, 4 * 8 + 8
+ call rax
+ add rsp, 4 * 8 + 8
+
+nonNullValue:
+ cli
+;; UINT64 ExceptionData;
+ add rsp, 8
+
+;; FX_SAVE_STATE_X64 FxSaveState;
+
+ mov rsi, rsp
+ db 0fh, 0aeh, 00001110y ; fxrstor [rsi]
+ add rsp, 512
+
+;; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
+ pop rax
+ mov dr0, rax
+ pop rax
+ mov dr1, rax
+ pop rax
+ mov dr2, rax
+ pop rax
+ mov dr3, rax
+;; skip restore of dr6. We cleared dr6 during the context save.
+ add rsp, 8
+ pop rax
+ mov dr7, rax
+
+;; UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;
+ pop rax
+ mov cr0, rax
+ add rsp, 8 ; not for Cr1
+ pop rax
+ mov cr2, rax
+ pop rax
+ mov cr3, rax
+ pop rax
+ mov cr4, rax
+ pop rax
+ mov cr8, rax
+
+;; UINT64 RFlags;
+ pop qword ptr [rbp + 40]
+
+;; UINT64 Ldtr, Tr;
+;; UINT64 Gdtr[2], Idtr[2];
+;; Best not let anyone mess with these particular registers...
+ add rsp, 48
+
+;; UINT64 Rip;
+ pop qword ptr [rbp + 24]
+
+;; UINT64 Gs, Fs, Es, Ds, Cs, Ss;
+ pop rax
+ ; mov gs, rax ; not for gs
+ pop rax
+ ; mov fs, rax ; not for fs
+ ; (X64 will not use fs and gs, so we do not restore it)
+ pop rax
+ mov es, rax
+ pop rax
+ mov ds, rax
+ pop qword ptr [rbp + 32] ; for cs
+ pop qword ptr [rbp + 56] ; for ss
+
+;; UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;
+;; UINT64 R8, R9, R10, R11, R12, R13, R14, R15;
+ pop rdi
+ pop rsi
+ add rsp, 8 ; not for rbp
+ pop qword ptr [rbp + 48] ; for rsp
+ pop rbx
+ pop rdx
+ pop rcx
+ pop rax
+ pop r8
+ pop r9
+ pop r10
+ pop r11
+ pop r12
+ pop r13
+ pop r14
+ pop r15
+
+ mov rsp, rbp
+ pop rbp
+ add rsp, 16
+ iretq
+
+CommonInterruptEntry ENDP
+
+
+LongMode PROC PUBLIC
+
+in_long_mode::
+ ;
+ ; Debug Stop
+ ;
+ jmp in_long_mode
+
+ ;
+ ; We're in long mode, so marshall the arguments to call the
+ ; passed in function pointers
+ ; Recall
+ ; [ebp][10h] = HobStart
+ ; [ebp][18h] = Stack
+ ; [ebp][20h] = PpisNeededByDxeIplEntryPoint <--- Call this first (for each call, pass HOB pointer)
+ ; [ebp][28h] = DxeCoreEntryPoint <--- Call this second
+ ;
+ mov rbx, [rbp+18h] ; Setup the stack
+ mov rsp, rbx ; On a new stack now
+
+ mov rcx, [rbp+10h] ; Pass Hob Start in RCX
+ mov rax, [rbp+20h] ; Get the function pointer for
+ ; PpisNeededByDxeIplEntryPoint into EAX
+ call fword ptr [rax] ; Make the call into PpisNeededByDxeIplEntryPoint
+
+ mov ecx, [rbp+10h] ; Pass Hob Start in RCX
+ mov eax, [rbp+28h] ; Get the function pointer for
+ ; DxeCoreEntryPoint into EAX
+ call fword ptr [rax] ; Make the call into Dxe Core
+
+ call CommonInterruptEntry
+
+ mov rdi, CommonInterruptEntry
+
+ lgdt fword ptr [rdi]
+
+ lidt fword ptr [rdi]
+
+ call near ptr [rax] ; Make the call into PpisNeededByDxeIplEntryPoint
+
+ call rax
+
+ ;
+ ; Should never get here.
+ ;
+no_long_mode:
+ jmp no_long_mode
+ ;
+ ; WE SHOULD NEVER GET HERE!!!!!!!!!!!!!
+ ;
+LongMode endp
+
+MpMtrrSynchUpEntry PROC PUBLIC
+ ;
+ ; Enter no fill cache mode, CD=1(Bit30), NW=0 (Bit29)
+ ;
+ mov rax, cr0
+ and rax, 0DFFFFFFFh
+ or rax, 040000000h
+ mov cr0, rax
+ ;
+ ; Flush cache
+ ;
+ wbinvd
+ ;
+ ; Clear PGE flag Bit 7
+ ;
+ mov rax, cr4
+ mov rdx, rax
+ and rax, 0FFFFFF7Fh
+ mov cr4, rax
+ ;
+ ; Flush all TLBs
+ ;
+ mov rax, cr3
+ mov cr3, rax
+
+ mov rax, rdx
+
+ ret
+
+MpMtrrSynchUpEntry ENDP
+
+MpMtrrSynchUpExit PROC PUBLIC
+ ;
+ ; Flush all TLBs the second time
+ ;
+ mov rax, cr3
+ mov cr3, rax
+ ;
+ ; Enable Normal Mode caching CD=NW=0, CD(Bit30), NW(Bit29)
+ ;
+ mov rax, cr0
+ and rax, 09FFFFFFFh
+ mov cr0, rax
+ ;
+ ; Set PGE Flag in CR4 if set
+ ;
+ mov cr4, rcx
+ ret
+
+MpMtrrSynchUpExit ENDP
+
+CpuInitFloatPointUnit PROC PUBLIC
+
+ ; bugbug
+ ; finit
+ ret
+
+CpuInitFloatPointUnit ENDP
+
+CpuDisableInterrupt PROC PUBLIC
+
+ cli
+ ret
+
+CpuDisableInterrupt ENDP
+
+CpuEnableInterrupt PROC PUBLIC
+
+ sti
+ ret
+
+CpuEnableInterrupt ENDP
+
+GetCoreNumber PROC PUBLIC
+
+ push rbx
+
+ mov eax, 4
+ mov ecx, 0
+ cpuid
+
+ shr eax, 26
+ and eax, 3fh
+ inc al
+
+ pop rbx
+
+ ret
+
+GetCoreNumber ENDP
+
+END
diff --git a/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/x64/CpuInitDxeGccDummy.c b/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/x64/CpuInitDxeGccDummy.c
new file mode 100644
index 0000000000..116497d3a9
--- /dev/null
+++ b/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/x64/CpuInitDxeGccDummy.c
@@ -0,0 +1,184 @@
+/** @file
+ CPU Dxe Gcc Support - Dummy functions.
+
+ Copyright (c) 1999 - 2015, 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.
+
+**/
+
+UINTN AsmIdtVector00;
+
+///
+/// Function declarations
+///
+/**
+ This is dummy function equivelant to the asm function CpuEnableInterrupt(), made for GCC build.
+**/
+VOID
+CpuEnableInterrupt (
+ VOID
+ )
+{
+ return;
+}
+
+/**
+ This is dummy function equivelant to the asm function CpuDisableInterrupt(), made for GCC build.
+**/
+VOID
+CpuDisableInterrupt (
+ VOID
+ )
+{
+ return;
+}
+
+/**
+ This is dummy function equivelant to the asm function AsmAcquireMPLock(), made for GCC build.
+**/
+VOID
+AsmAcquireMPLock (
+ VOID
+ )
+{
+ return;
+}
+
+/**
+ This is dummy function equivelant to the asm function AsmReleaseMPLock(), made for GCC build.
+**/
+VOID
+AsmReleaseMPLock (
+ VOID
+ )
+{
+ return;
+}
+
+/**
+ This is dummy function equivelant to the asm function AsmExchangeRole(), made for GCC build.
+**/
+VOID
+AsmExchangeRole (
+ VOID
+ )
+{
+ return;
+}
+
+/**
+ This is dummy function equivelant to the asm function CpuInitFloatPointUnit(), made for GCC build.
+**/
+VOID
+CpuInitFloatPointUnit (
+ VOID
+ )
+{
+ return;
+}
+
+/**
+ This is dummy function equivelant to the asm function MpMtrrSynchUpEntry(), made for GCC build.
+**/
+VOID
+MpMtrrSynchUpEntry (
+ VOID
+ )
+{
+ return;
+}
+
+/**
+ This is dummy function equivelant to the asm function MpMtrrSynchUpExit(), made for GCC build.
+**/
+VOID
+MpMtrrSynchUpExit (
+ VOID
+ )
+{
+ return;
+}
+
+/**
+ This is dummy function equivelant to the asm function CpuLoadGlobalDescriptorTable(), made for GCC build.
+**/
+VOID
+CpuLoadGlobalDescriptorTable (
+ VOID
+ )
+{
+ return;
+}
+
+/**
+ This is dummy function equivelant to the asm function CpuLoadInterruptDescriptorTable(), made for GCC build.
+**/
+VOID
+CpuLoadInterruptDescriptorTable (
+ VOID
+ )
+{
+ return;
+}
+
+/**
+ This is dummy function equivelant to the asm function InitializeExternalVectorTablePtr(), made for GCC build.
+**/
+VOID
+InitializeExternalVectorTablePtr (
+ VOID
+ )
+{
+ return;
+}
+
+/**
+ This is dummy function equivelant to the asm function CpuCodeSegment(), made for GCC build.
+**/
+VOID
+CpuCodeSegment (
+ VOID
+ )
+{
+ return;
+}
+
+/**
+ This is dummy function equivelant to the asm function AsmGetAddressMap(), made for GCC build.
+**/
+VOID
+AsmGetAddressMap (
+ VOID
+ )
+{
+ return;
+}
+
+/**
+ This is dummy function equivelant to the asm function AsmGetGdtrIdtr(), made for GCC build.
+**/
+VOID
+AsmGetGdtrIdtr (
+ VOID
+ )
+{
+ return;
+}
+
+/**
+ This is dummy function equivelant to the asm function AsmGetCr3(), made for GCC build.
+**/
+VOID
+AsmGetCr3 (
+ VOID
+ )
+{
+ return;
+}
diff --git a/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/x64/Exception.c b/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/x64/Exception.c
new file mode 100644
index 0000000000..4e4d4ed1c0
--- /dev/null
+++ b/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/x64/Exception.c
@@ -0,0 +1,319 @@
+/** @file
+ EM64T Exception Handler.
+
+ Copyright (c) 2014 - 2015, 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 "CpuDxe.h"
+#include "MpCommon.h"
+#include "Exception.h"
+
+typedef
+VOID
+(*EFI_INSTALL_EXCEPTION) (
+ IN UINT32 InterruptType,
+ IN VOID *SystemContext
+ );
+/**
+ @todo No structure description
+
+**/
+typedef struct {
+ UINT32 ErrorMessage;
+ UINT8 Interrupt;
+} EFI_EXCEPTION_HANDLER;
+
+//
+// Error code flag indicating whether or not an error code will be
+// pushed on the stack if an exception occurs.
+//
+// 1 means an error code will be pushed, otherwise 0
+//
+// bit 0 - exception 0
+// bit 1 - exception 1
+// etc.
+//
+UINT32 mErrorCodeFlag = 0x00027d00;
+
+//
+// Local Table
+//
+EFI_EXCEPTION_HANDLER mExceptionTable[] = {
+ { EFI_SW_EC_IA32_DIVIDE_ERROR, INTERRUPT_HANDLER_DIVIDE_ZERO },
+ { EFI_SW_EC_IA32_DEBUG, INTERRUPT_HANDLER_DEBUG },
+ { EFI_SW_EC_IA32_NMI, INTERRUPT_HANDLER_NMI },
+ { EFI_SW_EC_IA32_BREAKPOINT, INTERRUPT_HANDLER_BREAKPOINT },
+ { EFI_SW_EC_IA32_OVERFLOW, INTERRUPT_HANDLER_OVERFLOW },
+ { EFI_SW_EC_IA32_BOUND, INTERRUPT_HANDLER_BOUND },
+ { EFI_SW_EC_IA32_INVALID_OPCODE, INTERRUPT_HANDLER_INVALID_OPCODE },
+//
+// Interrupt 7, 9, 15 not defined in the debug support protocol. Hence no status codes for them!
+//
+ { EFI_SW_EC_IA32_DOUBLE_FAULT, INTERRUPT_HANDLER_DOUBLE_FAULT },
+ { EFI_SW_EC_IA32_INVALID_TSS, INTERRUPT_HANDLER_INVALID_TSS },
+ { EFI_SW_EC_IA32_SEG_NOT_PRESENT, INTERRUPT_HANDLER_SEGMENT_NOT_PRESENT },
+ { EFI_SW_EC_IA32_STACK_FAULT, INTERRUPT_HANDLER_STACK_SEGMENT_FAULT },
+ { EFI_SW_EC_IA32_GP_FAULT, INTERRUPT_HANDLER_GP_FAULT },
+ { EFI_SW_EC_IA32_PAGE_FAULT, INTERRUPT_HANDLER_PAGE_FAULT },
+ { EFI_SW_EC_IA32_FP_ERROR, INTERRUPT_HANDLER_MATH_FAULT },
+ { EFI_SW_EC_IA32_ALIGNMENT_CHECK, INTERRUPT_HANDLER_ALIGNMENT_FAULT },
+ { EFI_SW_EC_IA32_MACHINE_CHECK, INTERRUPT_HANDLER_MACHINE_CHECK },
+ { EFI_SW_EC_IA32_SIMD, INTERRUPT_HANDLER_STREAMING_SIMD }
+ };
+
+UINTN mExceptionNumber = sizeof (mExceptionTable) / sizeof (EFI_EXCEPTION_HANDLER);
+
+CPU_STATUS_CODE_TEMPLATE mStatusCodeData = {
+ {
+ sizeof (EFI_STATUS_CODE_DATA),
+ sizeof (EFI_SYSTEM_CONTEXT_X64),
+ EFI_STATUS_CODE_DATA_TYPE_EXCEPTION_HANDLER_GUID
+ },
+ {
+ 0
+ }
+};
+
+UINT8 mExceptionLock = 0;
+/**
+ Report StatusCode for Exception
+
+ @param[in] InterruptType Interrupt type
+ @param[in] SystemContext EFI_SYSTEM_CONTEXT
+
+ @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+ReportData (
+ IN EFI_EXCEPTION_TYPE InterruptType,
+ IN EFI_SYSTEM_CONTEXT SystemContext
+ )
+{
+ UINT32 ErrorMessage;
+ UINT32 Index;
+
+ CopyMem (
+ &mStatusCodeData.SystemContext.SystemContextX64,
+ SystemContext.SystemContextX64,
+ sizeof (EFI_SYSTEM_CONTEXT_X64)
+ );
+
+ ErrorMessage = EFI_SOFTWARE_DXE_BS_DRIVER;
+ for (Index = 0; Index < mExceptionNumber; Index++) {
+ if (mExceptionTable[Index].Interrupt == InterruptType) {
+ ErrorMessage |= mExceptionTable[Index].ErrorMessage;
+ break;
+ }
+ }
+
+ REPORT_STATUS_CODE_EX (
+ (EFI_ERROR_CODE | EFI_ERROR_UNRECOVERED),
+ EFI_SOFTWARE_UNSPECIFIED | ErrorMessage,
+ 0,
+ &gEfiCallerIdGuid,
+ NULL,
+ (EFI_STATUS_CODE_DATA *)&mStatusCodeData,
+ sizeof(CPU_STATUS_CODE_TEMPLATE)
+ );
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Common exception handler
+
+ @param[in] InterruptType Exception type
+ @param[in] SystemContext EFI_SYSTEM_CONTEXT
+
+**/
+VOID
+EFIAPI
+CommonExceptionHandler (
+ IN EFI_EXCEPTION_TYPE InterruptType,
+ IN EFI_SYSTEM_CONTEXT SystemContext
+ )
+{
+ AsmAcquireMPLock (&mExceptionLock);
+
+ DEBUG ((
+ DEBUG_ERROR,
+ "!!!! X64 Exception Type - %016lx CPU Apic ID - %08x!!!!\n",
+ InterruptType,
+ GetApicID (NULL, NULL)
+ ));
+ DEBUG ((
+ DEBUG_ERROR,
+ "RIP - %016lx, CS - %016lx, RFLAGS - %016lx\n",
+ SystemContext.SystemContextX64->Rip,
+ SystemContext.SystemContextX64->Cs,
+ SystemContext.SystemContextX64->Rflags
+ ));
+ if (mErrorCodeFlag & (1 << InterruptType)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "ExceptionData - %016lx\n",
+ SystemContext.SystemContextX64->ExceptionData
+ ));
+ }
+ DEBUG ((
+ DEBUG_ERROR,
+ "RAX - %016lx, RCX - %016lx, RDX - %016lx\n",
+ SystemContext.SystemContextX64->Rax,
+ SystemContext.SystemContextX64->Rcx,
+ SystemContext.SystemContextX64->Rdx
+ ));
+ DEBUG ((
+ DEBUG_ERROR,
+ "RBX - %016lx, RSP - %016lx, RBP - %016lx\n",
+ SystemContext.SystemContextX64->Rbx,
+ SystemContext.SystemContextX64->Rsp,
+ SystemContext.SystemContextX64->Rbp
+ ));
+ DEBUG ((
+ DEBUG_ERROR,
+ "RSI - %016lx, RDI - %016lx\n",
+ SystemContext.SystemContextX64->Rsi,
+ SystemContext.SystemContextX64->Rdi
+ ));
+ DEBUG ((
+ DEBUG_ERROR,
+ "R8 - %016lx, R9 - %016lx, R10 - %016lx\n",
+ SystemContext.SystemContextX64->R8,
+ SystemContext.SystemContextX64->R9,
+ SystemContext.SystemContextX64->R10
+ ));
+ DEBUG ((
+ DEBUG_ERROR,
+ "R11 - %016lx, R12 - %016lx, R13 - %016lx\n",
+ SystemContext.SystemContextX64->R11,
+ SystemContext.SystemContextX64->R12,
+ SystemContext.SystemContextX64->R13
+ ));
+ DEBUG ((
+ DEBUG_ERROR,
+ "R14 - %016lx, R15 - %016lx\n",
+ SystemContext.SystemContextX64->R14,
+ SystemContext.SystemContextX64->R15
+ ));
+ DEBUG ((
+ DEBUG_ERROR,
+ "DS - %016lx, ES - %016lx, FS - %016lx\n",
+ SystemContext.SystemContextX64->Ds,
+ SystemContext.SystemContextX64->Es,
+ SystemContext.SystemContextX64->Fs
+ ));
+ DEBUG ((
+ DEBUG_ERROR,
+ "GS - %016lx, SS - %016lx\n",
+ SystemContext.SystemContextX64->Gs,
+ SystemContext.SystemContextX64->Ss
+ ));
+ DEBUG ((
+ DEBUG_ERROR,
+ "GDTR - %016lx %016lx, LDTR - %016lx\n",
+ SystemContext.SystemContextX64->Gdtr[0],
+ SystemContext.SystemContextX64->Gdtr[1],
+ SystemContext.SystemContextX64->Ldtr
+ ));
+ DEBUG ((
+ DEBUG_ERROR,
+ "IDTR - %016lx %016lx, TR - %016lx\n",
+ SystemContext.SystemContextX64->Idtr[0],
+ SystemContext.SystemContextX64->Idtr[1],
+ SystemContext.SystemContextX64->Tr
+ ));
+ DEBUG ((
+ DEBUG_ERROR,
+ "CR0 - %016lx, CR2 - %016lx, CR3 - %016lx\n",
+ SystemContext.SystemContextX64->Cr0,
+ SystemContext.SystemContextX64->Cr2,
+ SystemContext.SystemContextX64->Cr3
+ ));
+ DEBUG ((
+ DEBUG_ERROR,
+ "CR4 - %016lx, CR8 - %016lx\n",
+ SystemContext.SystemContextX64->Cr4,
+ SystemContext.SystemContextX64->Cr8
+ ));
+ DEBUG ((
+ DEBUG_ERROR,
+ "DR0 - %016lx, DR1 - %016lx, DR2 - %016lx\n",
+ SystemContext.SystemContextX64->Dr0,
+ SystemContext.SystemContextX64->Dr1,
+ SystemContext.SystemContextX64->Dr2
+ ));
+ DEBUG ((
+ DEBUG_ERROR,
+ "DR3 - %016lx, DR6 - %016lx, DR7 - %016lx\n",
+ SystemContext.SystemContextX64->Dr3,
+ SystemContext.SystemContextX64->Dr6,
+ SystemContext.SystemContextX64->Dr7
+ ));
+
+ //
+ // Report Status Code
+ //
+ ReportData (InterruptType, SystemContext);
+
+ AsmReleaseMPLock (&mExceptionLock);
+
+ //
+ // Use this macro to hang so that the compiler does not optimize out
+ // the following RET instructions. This allows us to return if we
+ // have a debugger attached.
+ //
+ CpuDeadLoop ();
+
+ return ;
+}
+
+/**
+ Install the IA-32 EM64T Exception Handler.
+ The current operation (which likely will change) will uninstall all the
+ pertinent exception handlers (0-7, 10-14, 16-19) except for Int8 which the timer
+ is currently sitting on (or soon will be).
+
+ It then installs all the appropriate handlers for each exception.
+
+ The handler then calls gRT->ReportStatusCode with a specific progress code. The
+ progress codes for now start at 0x200 for IA-32 processors. See Status Code
+ Specification for details. The Status code Specification uses the enumeration from
+ the EFI 1.1 Debug Support Protocol.
+
+ @param[in] CpuProtocol - Instance of CPU Arch Protocol
+
+ @retval EFI_STATUS
+
+**/
+EFI_STATUS
+InitializeException (
+ IN EFI_CPU_ARCH_PROTOCOL *CpuProtocol
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+
+ Status = CpuProtocol->DisableInterrupt (CpuProtocol);
+
+ for (Index = 0; Index < mExceptionNumber; Index++) {
+ Status = CpuProtocol->RegisterInterruptHandler (CpuProtocol, mExceptionTable[Index].Interrupt, NULL);
+ //
+ // Add in our handler
+ //
+ Status = CpuProtocol->RegisterInterruptHandler (CpuProtocol, mExceptionTable[Index].Interrupt, CommonExceptionHandler);
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ return EFI_SUCCESS;
+}
+
diff --git a/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/x64/Htequ.inc b/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/x64/Htequ.inc
new file mode 100644
index 0000000000..d8a94ca9ea
--- /dev/null
+++ b/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/x64/Htequ.inc
@@ -0,0 +1,44 @@
+;; @file
+;
+; Copyright (c) 2005 - 2015, 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
+BreakToRunApSignal Equ 6E750000h
+
+MonitorFilterSize Equ 40h
+WakeUpApCounterInit Equ 0
+WakeUpApPerHltLoop Equ 1
+WakeUpApPerMwaitLoop Equ 2
+WakeUpApPerRunLoop Equ 3
+WakeUpApPerMwaitLoop32 Equ 4
+WakeUpApPerRunLoop32 Equ 5
+
+LockLocation equ 1000h - 0400h
+StackStartAddressLocation equ LockLocation + 08h
+StackSizeLocation equ LockLocation + 10h
+CProcedureLocation equ LockLocation + 18h
+GdtrLocation equ LockLocation + 20h
+IdtrLocation equ LockLocation + 2Ah
+BufferStartLocation equ LockLocation + 34h
+Cr3OffsetLocation equ LockLocation + 38h
+InitFlagLocation equ LockLocation + 3Ch
+WakeUpApManner equ LockLocation + 40h
+BistBuffer equ LockLocation + 44h
+
+PAUSE32 MACRO
+ DB 0F3h
+ DB 090h
+ ENDM
+
+;-------------------------------------------------------------------------------
diff --git a/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/x64/MemoryOperation.c b/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/x64/MemoryOperation.c
new file mode 100644
index 0000000000..83bfa8bf05
--- /dev/null
+++ b/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/x64/MemoryOperation.c
@@ -0,0 +1,718 @@
+/** @file
+ Memory Operation Functions for IA32 Architecture.
+
+ Copyright (c) 2014 - 2015, 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 "CpuDxe.h"
+#include "PlatformCpuLib.h"
+#include "MpCommon.h"
+#include "VirtualMemory.h"
+#include "MemoryAttribute.h"
+#include "CpuRegs.h"
+
+/**
+ This functions Initializes External Vector Table Pointer
+
+ @param[in] *VectorTable Pointer to Vector Table
+
+**/
+VOID
+InitializeExternalVectorTablePtr (
+ EFI_CPU_INTERRUPT_HANDLER* VectorTable
+);
+
+extern EFI_CPU_INTERRUPT_HANDLER mExternalVectorTable[];
+extern EFI_PHYSICAL_ADDRESS mBackupBuffer;
+
+UINT8 *mPageStore = NULL;
+UINTN mPageStoreSize = 16;
+UINTN mPageStoreIndex = 0;
+
+UINT64 mValidMtrrAddressMask;
+UINT64 mValidMtrrBitsMask;
+
+#if defined (__GNUC__)
+#define ALINE_16BYTE_BOUNDRY __attribute__ ((aligned (16)))
+#else
+#define ALINE_16BYTE_BOUNDRY __declspec (align (16))
+#endif
+
+#pragma pack (1)
+/**
+ @todo add description
+
+**/
+typedef struct {
+ UINT16 LimitLow;
+ UINT16 BaseLow;
+ UINT8 BaseMiddle;
+ UINT8 Attributes1;
+ UINT8 Attributes2;
+ UINT8 BaseHigh;
+} SEGMENT_DESCRIPTOR_x64;
+
+/**
+ @todo Add description
+
+**/
+
+typedef struct {
+ UINT16 Limit;
+ UINTN Base;
+} PSEUDO_DESCRIPTOR_x64;
+
+#pragma pack()
+
+ALINE_16BYTE_BOUNDRY SEGMENT_DESCRIPTOR_x64 gGdt[] = {
+ { // NULL Selector: selector[0]
+ 0, // limit 15:0
+ 0, // base 15:0
+ 0, // base 23:16
+ 0, //
+ 0, // type & limit 19:16
+ 0, // base 31:24
+ },
+ { // Linear Selector: selector[8]
+ 0xffff, // limit 15:0
+ 0, // base 15:0
+ 0, // base 23:16
+ 0x92, // present, ring 0, data, expand-up writable
+ 0xcf, // type & limit 19:16
+ 0, // base 31:24
+ },
+ { // Linear code Selector: selector[10]
+ 0xffff, // limit 15:0
+ 0, // base 15:0
+ 0, // base 23:16
+ 0x9a, // present, ring 0, code, expand-up writable
+ 0xaf, // type & limit 19:16
+ 0, // base 31:24
+ },
+ { // Compatibility mode data Selector: selector[18]
+ 0xffff, // limit 15:0
+ 0, // base 15:0
+ 0, // base 23:16
+ 0x92, // type & limit 19:16
+ 0xcf,
+ 0, // base 31:24
+ },
+ { // Compatibility code Selector: selector[20]
+ 0xffff, // limit 15:0
+ 0, // base 15:0
+ 0, // base 23:16
+ 0x9a, // type & limit 19:16
+ 0xcf,
+ 0, // base 31:24
+ },
+ { // Spare3 Selector: selector[28]
+ 0, // limit 15:0
+ 0, // base 15:0
+ 0, // base 23:16
+ 0, // type & limit 19:16
+ 0, // base 31:24
+ 0,
+ },
+ { // 64-bit data Selector:selector[30]
+ 0xffff, // limit 15:0
+ 0, // base 15:0
+ 0, // base 23:16
+ 0x92, // type & limit 19:16
+ 0xcf,
+ 0, // base 31:24
+ },
+ { // 64-bit code Selector: selector[38]
+ 0xffff, // limit 15:0
+ 0, // base 15:0
+ 0, // base 23:16
+ 0x9a, // type & limit 19:16
+ 0xaf,
+ 0, // base 31:24
+ },
+ { // Spare3 Selector: selector[40]
+ 0, // limit 15:0
+ 0, // base 15:0
+ 0, // base 23:16
+ 0, // type & limit 19:16
+ 0, // base 31:24
+ 0,
+ }
+};
+
+ALINE_16BYTE_BOUNDRY PSEUDO_DESCRIPTOR_x64 gGdtPseudoDescriptor = {
+ sizeof (gGdt) - 1,
+ (UINTN)gGdt
+};
+
+INTERRUPT_GATE_DESCRIPTOR gIdtTable[INTERRUPT_VECTOR_NUMBER] = { 0 };
+
+ALINE_16BYTE_BOUNDRY PSEUDO_DESCRIPTOR_x64 gLidtPseudoDescriptor = {
+ sizeof (gIdtTable) - 1,
+ (UINTN)gIdtTable
+};
+
+/**
+ @todo add function description
+
+**/
+VOID
+InitializeSelectors (
+ VOID
+ )
+{
+ CpuLoadGlobalDescriptorTable (&gGdtPseudoDescriptor);
+}
+
+VOID
+AsmIdtVector00 (
+ VOID
+ );
+/**
+ Slick around interrupt routines.
+
+**/
+VOID
+InitializeInterruptTables (
+ VOID
+ )
+{
+ UINT16 CodeSegment;
+ INTERRUPT_GATE_DESCRIPTOR *IdtEntry;
+ UINT8 *CurrentHandler;
+ UINT32 Index;
+
+ CodeSegment = CpuCodeSegment ();
+
+ IdtEntry = gIdtTable;
+ CurrentHandler = (UINT8 *)(UINTN)AsmIdtVector00;
+ for (Index = 0; Index < INTERRUPT_VECTOR_NUMBER; Index ++) {
+ IdtEntry[Index].Offset15To0 = (UINT16)(UINTN)CurrentHandler;
+ IdtEntry[Index].SegmentSelector = CodeSegment;
+ IdtEntry[Index].Attributes = INTERRUPT_GATE_ATTRIBUTE; //8e00;
+ IdtEntry[Index].Offset31To16 = (UINT16)((UINTN)CurrentHandler >> 16);
+ IdtEntry[Index].Offset63To32 = (UINT32)((UINTN)CurrentHandler >> 32);
+
+ CurrentHandler += 0x8;
+ }
+
+ CpuLoadInterruptDescriptorTable (&gLidtPseudoDescriptor);
+
+ return;
+}
+
+/**
+ @todo add function description
+
+**/
+VOID
+InitailizeMemoryAttributes (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS Page;
+ EFI_CPUID_REGISTER FeatureInfo;
+ EFI_CPUID_REGISTER FunctionInfo;
+ UINT8 PhysicalAddressBits;
+ UINT32 MsrNum, MsrNumEnd;
+ UINT64 TempQword;
+ UINT64 ComplementBits;
+
+ Status = gBS->AllocatePages (
+ AllocateAnyPages,
+ EfiBootServicesData,
+ mPageStoreSize,
+ &Page
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ mPageStore = (UINT8 *)(UINTN)Page;
+
+ ZeroMem (mPageStore, 0x1000 * mPageStoreSize);
+
+ ///
+ /// Check returned value of Eax for extended CPUID functions
+ ///
+ AsmCpuid (
+ EFI_CPUID_EXTENDED_FUNCTION,
+ &FunctionInfo.RegEax,
+ &FunctionInfo.RegEbx,
+ &FunctionInfo.RegEcx,
+ &FunctionInfo.RegEdx
+ );
+
+ PhysicalAddressBits = 36;
+
+ ///
+ /// If CPU supports extended functions, get the Physical Address size by reading EAX[7:0]
+ ///
+ if (FunctionInfo.RegEax > EFI_CPUID_VIRT_PHYS_ADDRESS_SIZE) {
+ AsmCpuid (
+ EFI_CPUID_VIRT_PHYS_ADDRESS_SIZE,
+ &FeatureInfo.RegEax,
+ &FeatureInfo.RegEbx,
+ &FeatureInfo.RegEcx,
+ &FeatureInfo.RegEdx
+ );
+ PhysicalAddressBits = (UINT8) FeatureInfo.RegEax;
+ }
+
+ mValidMtrrBitsMask = (((UINT64) 1) << PhysicalAddressBits) - 1;
+ mValidMtrrAddressMask = mValidMtrrBitsMask & 0xfffffffffffff000;
+
+ MsrNumEnd = EFI_MSR_CACHE_VARIABLE_MTRR_BASE + (2 * (UINT32)(AsmReadMsr64(EFI_MSR_IA32_MTRR_CAP) & B_EFI_MSR_IA32_MTRR_CAP_VARIABLE_SUPPORT)); //803 is put after PreMtrrChange()
+ ComplementBits = mValidMtrrBitsMask & 0xfffffff000000000;
+ if (ComplementBits != 0) {
+ PreMtrrChange ();
+ for (MsrNum = EFI_MSR_CACHE_VARIABLE_MTRR_BASE; MsrNum < MsrNumEnd; MsrNum += 2) {
+ TempQword = AsmReadMsr64 (MsrNum + 1);
+ if ((TempQword & B_EFI_MSR_CACHE_MTRR_VALID) != 0) {
+ //
+ // MTRR Physical Mask
+ //
+ TempQword = TempQword | ComplementBits;
+ AsmWriteMsr64 (MsrNum + 1, TempQword);
+ }
+ }
+ PostMtrrChange ();
+ }
+}
+
+/**
+ @todo add function description
+
+**/
+VOID *
+AllocateZeroedPage (
+ VOID
+ )
+{
+ if (mPageStoreIndex >= mPageStoreSize) {
+ //
+ // We are out of space
+ //
+ return NULL;
+ }
+
+ return (VOID *)(UINTN)&mPageStore[0x1000 * mPageStoreIndex++];
+}
+
+/**
+ This function converts 2 MB page to 4K pages
+
+ @param[in] PageAddress
+ @param[in] **PageDirectoryToConvert
+
+ @todo review parameters and description
+
+**/
+VOID
+Convert2MBPageTo4KPages (
+ IN EFI_PHYSICAL_ADDRESS PageAddress,
+ IN OUT x64_PAGE_TABLE_ENTRY **PageDirectoryToConvert
+ )
+{
+ UINTN Index;
+ EFI_PHYSICAL_ADDRESS WorkingAddress;
+ x64_PAGE_TABLE_ENTRY_4K *PageTableEntry;
+ x64_PAGE_TABLE_ENTRY Attributes;
+
+ //
+ // Save the attributes of the 2MB table
+ //
+ Attributes.Page2Mb.Uint64 = (*PageDirectoryToConvert)->Page2Mb.Uint64;
+
+ //
+ // Convert PageDirectoryEntry2MB into a 4K Page Directory
+ //
+ PageTableEntry = AllocateZeroedPage ();
+
+ if (PageTableEntry == NULL) {
+ ASSERT(PageTableEntry != NULL);
+ return;
+ }
+
+ (*PageDirectoryToConvert)->Page2Mb.Uint64 = (UINT64)PageTableEntry;
+ (*PageDirectoryToConvert)->Page2Mb.Bits.ReadWrite = 1;
+ (*PageDirectoryToConvert)->Page2Mb.Bits.Present = 1;
+
+ WorkingAddress = PageAddress;
+ for (Index = 0; Index < 512; Index++, PageTableEntry++, WorkingAddress += 0x1000) {
+ PageTableEntry->Uint64 = (UINT64)WorkingAddress;
+ PageTableEntry->Bits.Present = 1;
+
+ //
+ // Update the new page to have the same attributes as the 2MB page
+ //
+ PageTableEntry->Bits.ReadWrite = Attributes.Common.ReadWrite;
+ PageTableEntry->Bits.CacheDisabled = Attributes.Common.CacheDisabled;
+ PageTableEntry->Bits.WriteThrough = Attributes.Common.WriteThrough;
+
+ if (WorkingAddress == PageAddress) {
+ //
+ // Return back the 4K page that matches the Working addresss
+ //
+ *PageDirectoryToConvert = (x64_PAGE_TABLE_ENTRY *)PageTableEntry;
+ }
+ }
+}
+
+/**
+ @todo Add description to function
+
+ @param[in] BaseAddress @todo Add parameter description
+ @param[out] PageTable @todo Add parameter description
+ @param[out] Page2MBytes @todo Add parameter description
+
+ @retval @todo Add return value description
+
+**/
+EFI_STATUS
+GetCurrentMapping (
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ OUT x64_PAGE_TABLE_ENTRY **PageTable,
+ OUT BOOLEAN *Page2MBytes
+ )
+{
+ UINT64 Cr3;
+ x64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K *PageMapLevel4Entry;
+ x64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K *PageDirectoryPointerEntry;
+ x64_PAGE_TABLE_ENTRY_2M *PageTableEntry2Mb;
+ x64_PAGE_DIRECTORY_ENTRY_4K *PageDirectoryEntry4k;
+ x64_PAGE_TABLE_ENTRY_4K *PageTableEntry4k;
+ UINTN Pml4Index;
+ UINTN PdpIndex;
+ UINTN Pde2MbIndex;
+ UINTN PteIndex;
+
+ Cr3 = CpuReadCr3 ();
+
+ PageMapLevel4Entry = (x64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K *)(Cr3 & 0x000ffffffffff000);
+
+ Pml4Index = (UINTN)RShiftU64 (BaseAddress, 39) & 0x1ff;
+ if (PageMapLevel4Entry[Pml4Index].Bits.Present == 0) {
+ return EFI_NOT_FOUND;
+ }
+ PageDirectoryPointerEntry = (x64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K *)(PageMapLevel4Entry[Pml4Index].Uint64 & 0x000ffffffffff000);
+ PdpIndex = (UINTN)RShiftU64 (BaseAddress, 30) & 0x1ff;
+ if (PageDirectoryPointerEntry[PdpIndex].Bits.Present == 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ PageTableEntry2Mb = (x64_PAGE_TABLE_ENTRY_2M *)(PageDirectoryPointerEntry[PdpIndex].Uint64 & 0x000ffffffffff000);
+ Pde2MbIndex = (UINTN)RShiftU64 (BaseAddress, 21) & 0x1ff;
+ if (PageTableEntry2Mb[Pde2MbIndex].Bits.Present == 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ if (PageTableEntry2Mb[Pde2MbIndex].Bits.MustBe1 == 1) {
+ //
+ // We found a 2MByte page so lets return it
+ //
+ *Page2MBytes = TRUE;
+ *PageTable = (x64_PAGE_TABLE_ENTRY *)&PageTableEntry2Mb[Pde2MbIndex].Uint64;
+ return EFI_SUCCESS;
+ }
+
+ //
+ // 4K page so keep walking
+ //
+ PageDirectoryEntry4k = (x64_PAGE_DIRECTORY_ENTRY_4K *)&PageTableEntry2Mb[Pde2MbIndex].Uint64;
+
+ PageTableEntry4k = (x64_PAGE_TABLE_ENTRY_4K *)(PageDirectoryEntry4k[Pde2MbIndex].Uint64 & 0x000ffffffffff000);
+ PteIndex = (UINTN)RShiftU64 (BaseAddress, 12) & 0x1ff;
+ if (PageTableEntry4k[PteIndex].Bits.Present == 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ *Page2MBytes = FALSE;
+ *PageTable = (x64_PAGE_TABLE_ENTRY *)&PageTableEntry4k[PteIndex];
+ return EFI_SUCCESS;
+}
+
+/**
+ Prepare memory for essential system tables.
+
+ @retval EFI_SUCCESS Memory successfully prepared.
+
+**/
+EFI_STATUS
+PrepareMemory (
+ VOID
+ )
+{
+ //
+ // Allocate space to convert 2MB page tables to 4K tables.
+ // This can not be done a call time as the TPL level will
+ // not be correct.
+ //
+ InitailizeMemoryAttributes ();
+
+ InitializeExternalVectorTablePtr (mExternalVectorTable);
+ //
+ // Initialize the Interrupt Descriptor Table
+ //
+ InitializeInterruptTables ();
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Prepare Wakeup Buffer and stack for APs.
+
+ @param[out] WakeUpBuffer Pointer to the address of wakeup buffer for output.
+ @param[in] StackAddressStart Pointer to the stack address of APs for output.
+ @param[in] MaximumCPUsForThisSystem Maximum CPUs in this system.
+
+ @retval EFI_SUCCESS Memory successfully prepared for APs.
+ @retval Other Error occurred while allocating memory.
+
+**/
+EFI_STATUS
+PrepareMemoryForAPs (
+ OUT EFI_PHYSICAL_ADDRESS *WakeUpBuffer,
+ OUT VOID **StackAddressStart,
+ IN UINTN MaximumCPUsForThisSystem
+ )
+{
+ EFI_STATUS Status;
+ MP_ASSEMBLY_ADDRESS_MAP AddressMap;
+
+ //
+ // Release All APs with a lock and wait for them to retire to rendezvous procedure.
+ // We need a 64 aligned 4K aligned area for IA-32 to use broadcast APIs. But we need it only
+ // on a temporary basis.
+ //
+ Status = AllocateWakeUpBuffer (WakeUpBuffer);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Claim memory for AP stack.
+ //
+ Status = AllocateReservedMemoryBelow4G (
+ (MaximumCPUsForThisSystem + 1) * STACK_SIZE_PER_PROC,
+ (VOID **) StackAddressStart
+ );
+
+ if (EFI_ERROR (Status)) {
+ gBS->FreePages (*WakeUpBuffer, 1);
+ return Status;
+ }
+
+ AsmGetAddressMap (&AddressMap);
+ CopyMem ((VOID *) (UINTN) *WakeUpBuffer, AddressMap.RendezvousFunnelAddress, AddressMap.Size);
+ *(UINT32 *) (UINTN) (*WakeUpBuffer + AddressMap.FlatJumpOffset + 3) = (UINT32) (*WakeUpBuffer + AddressMap.PModeEntryOffset);
+ *(UINT32 *) (UINTN) (*WakeUpBuffer + AddressMap.LongJumpOffset + 2) = (UINT32) (*WakeUpBuffer + AddressMap.LModeEntryOffset);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Prepare exchange information for APs.
+
+ @param[out] ExchangeInfo Pointer to the exchange info buffer for output.
+ @param[in] StackAddressStart Start address of APs' stacks.
+ @param[in] ApFunction Address of function assigned to AP.
+ @param[in] WakeUpBuffer Pointer to the address of wakeup buffer.
+
+ @retval EFI_SUCCESS Exchange Info successfully prepared for APs.
+
+**/
+EFI_STATUS
+PrepareExchangeInfo (
+ OUT MP_CPU_EXCHANGE_INFO *ExchangeInfo,
+ IN VOID *StackAddressStart,
+ IN VOID *ApFunction,
+ IN EFI_PHYSICAL_ADDRESS WakeUpBuffer
+ )
+{
+ gBS->SetMem ((VOID *) ExchangeInfo, EFI_PAGE_SIZE - MP_CPU_EXCHANGE_INFO_OFFSET, 0);
+
+ ExchangeInfo->Lock = VacantFlag;
+ ExchangeInfo->StackStart = StackAddressStart;
+ ExchangeInfo->StackSize = STACK_SIZE_PER_PROC;
+ ExchangeInfo->ApFunction = ApFunction;
+
+ CopyMem ((VOID *) (UINTN) &ExchangeInfo->GdtrProfile, (VOID *) (UINTN) mAcpiCpuData->GdtrProfile, sizeof (IA32_DESCRIPTOR));
+ CopyMem ((VOID *) (UINTN) &ExchangeInfo->IdtrProfile, (VOID *) (UINTN) mAcpiCpuData->IdtrProfile, sizeof (IA32_DESCRIPTOR));
+
+ ExchangeInfo->BufferStart = (UINT32) WakeUpBuffer;
+ ExchangeInfo->Cr3 = (UINT32) (AsmGetCr3 ());
+ ExchangeInfo->InitFlag = 1;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Prepare Wakeup Buffer and stack for APs.
+
+ @param[out] WakeUpBuffer Pointer to the address of wakeup buffer for output.
+ @param[out] StackAddressStart Pointer to the stack address of APs for output.
+
+ @retval EFI_SUCCESS Memory successfully prepared for APs.
+
+**/
+EFI_STATUS
+S3PrepareMemoryForAPs (
+ OUT EFI_PHYSICAL_ADDRESS *WakeUpBuffer,
+ OUT VOID **StackAddressStart
+ )
+{
+ return EFI_SUCCESS;
+}
+
+/**
+ Prepare exchange information for APs.
+
+ @param[out] ExchangeInfo Pointer to the exchange info for output.
+ @param[in] StackAddressStart Start address of APs' stacks.
+ @param[in] ApFunction Address of function assigned to AP.
+ @param[in] WakeUpBuffer Pointer to the address of wakeup buffer.
+
+ @retval EFI_SUCCESS Exchange Info successfully prepared for APs.
+
+**/
+EFI_STATUS
+S3PrepareExchangeInfo (
+ OUT MP_CPU_EXCHANGE_INFO *ExchangeInfo,
+ IN VOID *StackAddressStart,
+ IN VOID *ApFunction,
+ IN EFI_PHYSICAL_ADDRESS WakeUpBuffer
+ )
+{
+ return EFI_SUCCESS;
+}
+
+/**
+ Dynamically write the far jump destination in APs' wakeup buffer,
+ in order to refresh APs' CS registers for mode switching.
+
+**/
+VOID
+RedirectFarJump (
+ VOID
+ )
+{
+ MP_ASSEMBLY_ADDRESS_MAP AddressMap;
+
+ AsmGetAddressMap (&AddressMap);
+ *(UINT32 *) (UINTN) (mAcpiCpuData->WakeUpBuffer + AddressMap.FlatJumpOffset + 3) = (UINT32) (mAcpiCpuData->WakeUpBuffer + AddressMap.PModeEntryOffset);
+ *(UINT32 *) (UINTN) (mAcpiCpuData->WakeUpBuffer + AddressMap.LongJumpOffset + 2) = (UINT32) (mAcpiCpuData->WakeUpBuffer + AddressMap.LModeEntryOffset);
+
+ return;
+}
+
+/**
+ Set specified IDT entry with given function pointer.
+
+ @param[in] FunctionPointer Function pointer for IDT entry.
+ @param[out] IdtEntry The IDT entry to update.
+
+ @retval The original IDT entry value.
+
+**/
+UINTN
+SetIdtEntry (
+ IN UINTN FunctionPointer,
+ OUT INTERRUPT_GATE_DESCRIPTOR *IdtEntry
+)
+{
+ UINTN OriginalEntry;
+
+ OriginalEntry = ((UINT64) IdtEntry->Offset63To32 << 32) + ((UINT32) IdtEntry->Offset31To16 << 16) + IdtEntry->Offset15To0;
+
+ IdtEntry->Offset15To0 = (UINT16) FunctionPointer;
+ IdtEntry->Offset31To16 = (UINT16) (FunctionPointer >> 16);
+ IdtEntry->Offset63To32 = (UINT32) (FunctionPointer >> 32);
+
+ return OriginalEntry;
+}
+
+/**
+ @todo Add function description
+
+ @param[in] Gdtr @todo add argument description for *Gdtr
+ @param[in] Idtr @todo add argument description for *Idtr
+
+ @retval EFI_SUCCESS This function completed successfully
+
+**/
+EFI_STATUS
+PrepareGdtIdtForAP (
+ OUT IA32_DESCRIPTOR *Gdtr,
+ OUT IA32_DESCRIPTOR *Idtr
+ )
+{
+ INTERRUPT_GATE_DESCRIPTOR *IdtForAP;
+ SEGMENT_DESCRIPTOR *GdtForAP;
+ IA32_DESCRIPTOR *IdtrForBSP;
+ IA32_DESCRIPTOR *GdtrForBSP;
+ UINT16 *MceHandler;
+ EFI_STATUS Status;
+
+ AsmGetGdtrIdtr (&GdtrForBSP, &IdtrForBSP);
+
+ //
+ // Allocate reserved memory for IDT
+ //
+ Status = AllocateAlignedReservedMemory (
+ IdtrForBSP->Limit + 1,
+ 8,
+ (VOID **) &IdtForAP
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Allocate reserved memory for GDT
+ //
+ Status = AllocateAlignedReservedMemory (
+ GdtrForBSP->Limit + 1,
+ 8,
+ (VOID **) &GdtForAP
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = gBS->AllocatePool (
+ EfiACPIMemoryNVS,
+ SIZE_OF_MCE_HANDLER,
+ (VOID **)&MceHandler
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // McheHandler content: iret (opcode = 0xcf)
+ //
+ *MceHandler = 0xCF48;
+
+ CopyMem (GdtForAP, (VOID *) GdtrForBSP->Base, GdtrForBSP->Limit + 1);
+ CopyMem (IdtForAP, (VOID *) IdtrForBSP->Base, IdtrForBSP->Limit + 1);
+
+ IdtForAP[INTERRUPT_HANDLER_MACHINE_CHECK].Offset15To0 = (UINT16) (UINTN) MceHandler;
+ IdtForAP[INTERRUPT_HANDLER_MACHINE_CHECK].Offset31To16 = (UINT16) ((UINTN) MceHandler >> 16);
+ IdtForAP[INTERRUPT_HANDLER_MACHINE_CHECK].Offset63To32 = (UINT32) ((UINTN) MceHandler >> 32);
+
+ //
+ // Create Gdtr, IDTR profile
+ //
+ Gdtr->Base = (UINTN) GdtForAP;
+ Gdtr->Limit = GdtrForBSP->Limit;
+
+ Idtr->Base = (UINTN) IdtForAP;
+ Idtr->Limit = IdtrForBSP->Limit;
+
+ return EFI_SUCCESS;
+}
diff --git a/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/x64/MpCpu.c b/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/x64/MpCpu.c
new file mode 100644
index 0000000000..7ef2f43ba1
--- /dev/null
+++ b/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/x64/MpCpu.c
@@ -0,0 +1,76 @@
+/** @file
+ MP Support driver.
+
+ Copyright (c) 2007 - 2015, 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 "CpuDxe.h"
+#include "MpCommon.h"
+#include "PlatformMpService.h"
+
+extern EFI_CPU_MICROCODE_HEADER **mMicrocodePointerBuffer;
+
+ACPI_CPU_DATA_COMPATIBILITY *mAcpiCpuData;
+MP_SYSTEM_DATA *mMPSystemData;
+
+/**
+ Initializes MP support in the system.
+
+ @param[in] ImageHandle Image handle of the loaded driver
+ @param[in] SystemTable Pointer to the System Table
+
+ @retval EFI_SUCCESS Multiple processors are initialized successfully.
+ @retval EFI_NOT_FOUND The ACPI variable is not found in S3 boot path.
+ @retval EFI_OUT_OF_RESOURCES No enough resoruces (such as out of memory).
+
+**/
+EFI_STATUS
+InitializeMpSupport (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ MP_CPU_RESERVED_DATA *MpCpuReservedData;
+
+ MpCpuReservedData = NULL;
+
+ Status = AllocateReservedMemoryBelow4G (
+ sizeof (MP_CPU_RESERVED_DATA),
+ (VOID **) &MpCpuReservedData
+ );
+
+ if ((EFI_ERROR (Status)) || (MpCpuReservedData == NULL)) {
+ return Status;
+ }
+
+ ZeroMem (MpCpuReservedData, sizeof (MP_CPU_RESERVED_DATA));
+
+ mMPSystemData = &(MpCpuReservedData->MPSystemData);
+ mAcpiCpuData = &(MpCpuReservedData->AcpiCpuData);
+
+ CopyMem (
+ MpCpuReservedData->MicrocodePointerBuffer,
+ mMicrocodePointerBuffer,
+ sizeof (EFI_CPU_MICROCODE_HEADER *) * (NUMBER_OF_MICROCODE_UPDATE + 1)
+ );
+
+ mAcpiCpuData->CpuPrivateData = (EFI_PHYSICAL_ADDRESS)(UINTN)(&(mMPSystemData->S3DataPointer));
+ mAcpiCpuData->S3BootPath = FALSE;
+ mAcpiCpuData->MicrocodePointerBuffer = (EFI_PHYSICAL_ADDRESS) MpCpuReservedData->MicrocodePointerBuffer;
+ mAcpiCpuData->GdtrProfile = (EFI_PHYSICAL_ADDRESS) & (MpCpuReservedData->GdtrProfile);
+ mAcpiCpuData->IdtrProfile = (EFI_PHYSICAL_ADDRESS) & (MpCpuReservedData->IdtrProfile);
+
+ MpServiceInitialize ();
+
+ return EFI_SUCCESS;
+}
diff --git a/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/x64/MpFuncs.asm b/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/x64/MpFuncs.asm
new file mode 100644
index 0000000000..9970dfba48
--- /dev/null
+++ b/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/x64/MpFuncs.asm
@@ -0,0 +1,604 @@
+;; @file
+; This is the assembly code for EM64T MP support.
+;
+; Copyright (c) 1999 - 2015, 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 Htequ.inc
+;-------------------------------------------------------------------------------------
+
+;-------------------------------------------------------------------------------------
+;RendezvousFunnelProc 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.
+;-------------------------------------------------------------------------------------
+;RendezvousFunnelProc (&WakeUpBuffer,MemAddress);
+
+text SEGMENT
+
+RendezvousFunnelProc PROC PUBLIC
+RendezvousFunnelProcStart::
+
+; At this point CS = 0x(vv00) and ip= 0x0.
+ db 66h, 08bh, 0e8h ; mov ebp, eax
+
+ 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
+
+; Get APIC ID
+;
+ db 66h, 0B8h
+ dd 00000001h ; mov eax, 1
+ db 0Fh, 0A2h ; cpuid
+ db 66h, 0C1h, 0EBh, 18h ; shr ebx, 24
+ db 66h, 81h, 0E3h
+ dd 000000FFh ; and ebx, 0ffh ; EBX is APIC ID
+
+; If it is the first time AP wakes up, just record AP's BIST
+; Otherwise, switch to protected mode.
+
+ db 0BEh ; opcode of mov si, imm16
+ dw InitFlagLocation ; mov si, InitFlag
+ db 66h, 83h, 3Ch, 00h ; cmp dword ptr [si], 0
+ db 74h ; opcode of jz
+ db flat32Start - ($ + 1) ; jz flat32Start
+
+; Record BIST information
+;
+ db 0B0h, 08h ; mov al, 8
+ db 0F6h, 0E3h ; mul bl
+
+ db 0BEh ; opcode of mov si, imm16
+ dw BistBuffer ; mov si, BistBuffer
+ db 03h, 0F0h ; add si, ax
+
+ db 66h, 0C7h, 04h
+ dd 00000001h ; mov dword ptr [si], 1 ; Set Valid Flag
+ db 66h, 89h, 6Ch, 04h ; mov dword ptr [si + 4], ebp ; Store BIST value
+
+ cli
+ hlt
+ jmp $-2
+
+;
+; Switch to flat mode.
+;
+flat32Start::
+
+ db 0BFh ; opcode of mov di, imm16
+ dw BufferStartLocation ; mov di, BufferStartLocation
+ db 66h, 8Bh, 35h ; mov esi,dword ptr [di] ; ESI is keeping the start address of wakeup buffer
+
+ db 0BFh ; opcode of mov di, imm16
+ dw Cr3OffsetLocation ; mov di, Cr3Location
+ db 66h, 8Bh, 0Dh ; mov ecx,dword ptr [di] ; ECX is keeping the value of CR3
+
+ db 0BFh ; opcode of mov di, imm16
+ dw GdtrLocation ; mov di, GdtrProfile
+ db 66h ; db 66h
+ db 2Eh, 0Fh, 01h, 15h ; lgdt fword ptr cs:[di]
+
+ db 0BFh ; opcode of mov di, imm16
+ dw IdtrLocation ; mov di, IdtrProfile
+ db 66h ; db 66h
+ db 2Eh, 0Fh, 01h, 1Dh ; lidt fword ptr cs:[di]
+
+ db 0BFh ; opcode of mov di, imm16
+ dw LongModeStartJump - RendezvousFunnelProcStart ; Get offset of LongModeStartJump
+ db 66h, 8Bh, 3Dh ; mov edi,dword ptr [di] ; EDI is keeping the LongModeStart Jump Address
+
+ db 31h, 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) and MP
+ db 0Fh, 22h, 0C0h ; mov cr0, eax
+
+FLAT32_JUMP::
+
+ db 66h, 67h, 0EAh ; far jump
+ dd 0h ; 32-bit offset
+ dw 20h ; 16-bit selector
+
+NemInit:: ; 32-bits 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.
+
+
+PrepareToGoLongMode64::
+
+ db 0Fh, 20h, 0E0h ; mov eax, cr4
+ db 66h, 0Dh, 020h, 06h ; or ax, 0620h ; Set PAE=1, OSFXSR=1, OSXMMEXCPT=1.
+ db 0Fh, 22h, 0E0h ; mov cr4, eax
+
+ db 0Fh, 22h, 0D9h ; mov cr3, ecx
+
+ db 0B9h
+ dd 0C0000080h ; mov ecx, 0c0000080h ; EFER MSR number.
+ db 0Fh, 32h ; rdmsr ; Read EFER.
+ db 0Fh, 0BAh, 0E8h, 08h ; bts eax, 8 ; Set LME=1.
+ db 0Fh, 30h ; wrmsr ; Write EFER.
+
+ db 0Fh, 20h, 0C0h ; mov eax, cr0 ; Read CR0.
+ db 0Fh, 0BAh, 0E8h, 1Fh ; bts eax, 31 ; Set PG=1.
+ db 0Fh, 22h, 0C0h ; mov cr0, eax ; Write CR0.
+
+LONG_JUMP::
+
+ db 67h, 0EAh ; far jump
+
+LongModeStartJump:
+
+ dd 0h ; 32-bit offset
+ dw 38h ; 16-bit selector
+
+
+LongModeStart::
+
+ mov ax, 30h
+ mov ds, ax
+ mov es, ax
+ mov ss, ax
+;
+; Patch Addresses for jumping between RUN and MONITOR MWAIT loops 32-bits and Long Monde Procedure 64-bits
+; Based on the running address of LongModeStart in physic memory which was actually copied by CPU DXE INIT
+;
+ xor rdx, rdx
+ mov eax, edi
+ add eax, RunLoopAndMwaitLoop32 - LongModeStart
+ mov edx, edi
+ add edx, RunLoopAndMwaitLoop32Jump - LongModeStart
+ mov dword ptr [rdx], eax
+
+ mov rbp, rdx ; RBP = 32-bits compatibility mode FAR JUMP m16:32 operand pointer
+
+ mov eax, edi
+ add eax, RunLoopAndMwaitLoop64 - LongModeStart
+ mov edx, edi
+ add edx, RunLoopAndMwaitLoop64Jump - LongModeStart
+ mov dword ptr [rdx], eax
+
+;
+; ProgramStack
+;
+ xor rcx, rcx
+ mov edi, esi
+ add edi, BistBuffer
+ mov ecx, dword ptr [edi + 8 * ebx] ; RCX = CpuNumber
+
+ mov edi, esi
+ add edi, StackSizeLocation
+ mov rax, qword ptr [edi]
+ inc rcx
+ mul rcx ; RAX = StackSize * (CpuNumber + 1)
+
+ mov edi, esi
+ add edi, StackStartAddressLocation
+ mov rdx, qword ptr [edi]
+ add rax, rdx ; RAX = StackStart + StackSize * (CpuNumber + 1)
+
+ mov rsp, rax
+ sub rsp, MonitorFilterSize ; Reserved Monitor data space
+ or ebx, BreakToRunApSignal ; ebx = #Cpu run signature
+
+;
+; Load C Function pointer and wakeup manner location
+;
+ mov edi, esi
+ add edi, CProcedureLocation
+ add esi, WakeUpApManner ; esi = WakeUpApManner Address Location
+
+WakeUpThisAp64::
+
+ mov rax, qword ptr [edi]
+
+ test rax, rax
+ jz CheckWakeUpCounterInit64
+
+ push rbp
+ push rbx
+ push rsi
+ push rdi
+
+ sub rsp, 20h
+ call rax
+ add rsp, 20h
+
+ pop rdi
+ pop rsi
+ pop rbx
+ pop rbp
+
+CheckWakeUpCounterInit64::
+
+ cmp dword ptr [esi], WakeUpApCounterInit
+ jnz CheckWakeUpManner64
+
+;
+; Initialize MONITOR_MWAIT_DATA data structure per thread
+;
+ xor rcx, rcx
+ mov qword ptr [rsp + 0], rcx ; BreakToRunApSignal
+ mov qword ptr [rsp + 8], rcx ; HltLoopBreakCounter
+ mov qword ptr [rsp + 16], rcx ; MwaitLoopBreakCounter
+ mov qword ptr [rsp + 24], rcx ; RunLoopBreakCounter
+ mov qword ptr [rsp + 32], rcx ; MwaitLoopBreakCounter32
+ mov qword ptr [rsp + 40], rcx ; RunLoopBreakCounter32
+ mov qword ptr [rsp + 48], rcx ; WakeUpApVectorChangeFlag
+ mov qword ptr [rsp + 56], rcx ; MwaitTargetCstate
+
+WaitWakeUpMannerAssigned::
+
+ pause
+ cmp dword ptr [esi], WakeUpApCounterInit
+ jz WaitWakeUpMannerAssigned
+
+CheckWakeUpManner64::
+
+ pause
+ mov edx, dword ptr [esi]
+ cmp edx, WakeUpApPerHltLoop
+ jz HltApLoop64
+
+ cmp edx, WakeUpApPerMwaitLoop
+ jz ApMwaitLoop64
+
+ cmp edx, WakeUpApPerRunLoop
+ jz CheckRunSignal64
+
+ jmp JumpToCompatibility32Mode
+
+ApMwaitLoop64::
+
+ cli
+ mov rax, rsp ; Set Monitor Address
+ xor rcx, rcx
+ xor rdx, rdx
+ DB 0fh, 1, 0c8h ; MONITOR
+ mov rax, qword ptr [rsp + 56] ; Mwait Target C-State per rax[7:4]
+ DB 0fh, 1, 0c9h ; MWAIT
+
+CheckRunSignal64::
+
+ cmp qword ptr [rsp], rbx ; Check if run signal correct?
+ jnz CheckWakeUpManner64 ; Unknown break, go checking run manner
+
+ jmp WakeUpThisAp64 ; Jmp to execute AP task
+
+HltApLoop64::
+
+ cli
+ hlt
+ jmp HltApLoop64 ; Jump to halt loop
+
+
+JumpToCompatibility32Mode::
+
+ db 0FFh, 6Dh, 0 ; jmp pword ptr [rbp+0] ; Far jump to m16:32 for 32-bits compatibility mode
+
+RunLoopAndMwaitLoop32Jump:
+
+ dd 0h ; m32 part of m16:32
+ dw 20h ; m16 part of m16:32
+
+RunLoopAndMwaitLoop32::
+
+ db 66h, 0B8h, 18h, 00h ; mov ax, 18h
+ db 66h, 8Eh, 0D8h ; mov ds, ax
+ db 8eh, 0d0h ; mov ss, ax
+
+ db 0Fh, 20h, 0C0h ; mov eax, cr0 ; Read CR0.
+ db 0Fh, 0BAh, 0F0h, 1Fh ; btr eax, 31 ; Reset PG=0.
+ db 0Fh, 22h, 0C0h ; mov cr0, eax ; Write CR0.
+
+ db 0B9h
+ dd 0C0000080h ; mov ecx, 0c0000080h ; EFER MSR number.
+ db 0Fh, 32h ; rdmsr ; Read EFER.
+ db 0Fh, 0BAh, 0F0h, 08h ; btr eax, 8 ; Reset LME=0.
+ db 0Fh, 30h ; wrmsr ; Write EFER.
+
+ db 0Fh, 20h, 0E0h ; mov eax, cr4
+ db 24h, 0DFh ; and al, 0DFh ; Reset PAE=0 in CR4 bit 5
+ db 0Fh, 22h, 0E0h ; mov cr4, eax
+
+CheckWakeUpManner32::
+
+ pause
+ cmp dword ptr [rsi], WakeUpApPerMwaitLoop32 ; Use rsi for esi per compling in 64-bits mode
+ jnz CheckRunSignal32
+
+ cli
+ mov eax, esp ; Set Monitor Address
+ xor ecx, ecx
+ xor edx, edx
+ DB 0fh, 1, 0c8h ; MONITOR
+ mov eax, dword ptr [rsp + 56] ; Mwait Target C-State per eax[7:4]
+ DB 0fh, 1, 0c9h ; MWAIT
+
+
+CheckRunSignal32::
+
+ cmp dword ptr [rsp], ebx ; Check if run signal correct?
+ jnz CheckWakeUpManner32 ; Unknown break, go checking run manner
+
+ db 0Fh, 20h, 0E0h ; mov eax, cr4
+ db 0Ch, 20h ; or al, 20h ; Set PAE=1 in CR4 bit 5
+ db 0Fh, 22h, 0E0h ; mov cr4, eax
+
+ db 0B9h
+ dd 0C0000080h ; mov ecx, 0c0000080h ; EFER MSR number.
+ db 0Fh, 32h ; rdmsr ; Read EFER.
+ db 0Fh, 0BAh, 0E8h, 08h ; bts eax, 8 ; Set LME=1.
+ db 0Fh, 30h ; wrmsr ; Write EFER.
+
+ db 0Fh, 20h, 0C0h ; mov eax, cr0 ; Read CR0.
+ db 0Fh, 0BAh, 0E8h, 1Fh ; bts eax, 31 ; Set PG=1.
+ db 0Fh, 22h, 0C0h ; mov cr0, eax ; Write CR0.
+
+ db 67h, 0EAh ; far jump back to 64-bits long mode
+
+RunLoopAndMwaitLoop64Jump:
+
+ dd 0h ; 32-bit offset
+ dw 38h ; 16-bit selector
+
+RunLoopAndMwaitLoop64::
+
+ mov ax, 30h
+ mov ds, ax
+ mov ss, ax
+
+ jmp WakeUpThisAp64
+
+RendezvousFunnelProc ENDP
+RendezvousFunnelProcEnd::
+
+
+;-------------------------------------------------------------------------------------
+; AsmGetAddressMap (&AddressMap);
+;-------------------------------------------------------------------------------------
+AsmGetAddressMap PROC PUBLIC
+
+ mov rax, offset RendezvousFunnelProcStart
+ mov qword ptr [rcx], rax
+ mov qword ptr [rcx+8h], NemInit - RendezvousFunnelProcStart
+ mov qword ptr [rcx+10h], FLAT32_JUMP - RendezvousFunnelProcStart
+ mov qword ptr [rcx+18h], LongModeStart - RendezvousFunnelProcStart
+ mov qword ptr [rcx+20h], LONG_JUMP - RendezvousFunnelProcStart
+ mov qword ptr [rcx+28h], RendezvousFunnelProcEnd - RendezvousFunnelProcStart
+
+ ret
+
+AsmGetAddressMap ENDP
+
+AsmGetGdtrIdtr PROC PUBLIC
+
+ sgdt GdtDesc
+ lea rax, GdtDesc
+ mov [rcx], rax
+
+ sidt IdtDesc
+ lea rax, IdtDesc
+ mov [rdx], rax
+
+ ret
+
+AsmGetGdtrIdtr ENDP
+
+AsmGetCr3 PROC PUBLIC
+
+ mov rax, cr3
+ ret
+
+AsmGetCr3 ENDP
+
+
+AsmAcquireMPLock PROC PUBLIC
+
+ mov al, NotVacantFlag
+TryGetLock:
+ xchg al, byte ptr [rcx]
+ cmp al, VacantFlag
+ jz LockObtained
+
+ pause
+ jmp TryGetLock
+
+LockObtained:
+ ret
+
+AsmAcquireMPLock ENDP
+
+AsmReleaseMPLock PROC PUBLIC
+
+ mov al, VacantFlag
+ xchg al, byte ptr [rcx]
+
+ ret
+
+AsmReleaseMPLock ENDP
+
+;-------------------------------------------------------------------------------------
+;AsmExchangeRole procedure follows. This procedure executed by current BSP, that is
+;about to become an AP. It switches it'stack with the current AP.
+;AsmExchangeRole (IN CPU_EXCHANGE_INFO *MyInfo, IN CPU_EXCHANGE_INFO *OthersInfo);
+;-------------------------------------------------------------------------------------
+CPU_SWITCH_STATE_IDLE equ 0
+CPU_SWITCH_STATE_STORED equ 1
+CPU_SWITCH_STATE_LOADED equ 2
+
+AsmExchangeRole PROC PUBLIC
+ ; DO NOT call other functions in this function, since 2 CPU may use 1 stack
+ ; at the same time. If 1 CPU try to call a functiosn, stack will be corrupted.
+
+ push rax
+ push rbx
+ push rcx
+ push rdx
+ push rsi
+ push rdi
+ push rbp
+ push r8
+ push r9
+ push r10
+ push r11
+ push r12
+ push r13
+ push r14
+ push r15
+
+ mov rax, cr0
+ push rax
+
+ mov rax, cr4
+ push rax
+
+ ; rsi contains MyInfo pointer
+ mov rsi, rcx
+
+ ; rdi contains OthersInfo pointer
+ mov rdi, rdx
+
+ ;Store EFLAGS, GDTR and IDTR regiter to stack
+ pushfq
+ sgdt fword ptr [rsi + 16]
+ sidt fword ptr [rsi + 26]
+
+ ; Store the its StackPointer
+ mov qword ptr [rsi + 8], rsp
+
+ ; update its switch state to STORED
+ mov al, NotVacantFlag
+TryLock1:
+ db 0f0h ; opcode for lock instruction
+ xchg al, byte ptr [rsi]
+ cmp al, VacantFlag
+ jz LockObtained1
+ pause
+ jmp TryLock1
+
+LockObtained1:
+ mov byte ptr [rsi + 1], CPU_SWITCH_STATE_STORED
+ db 0f0h ; opcode for lock instruction
+ xchg al, byte ptr [rsi]
+
+WaitForOtherStored::
+ ; wait until the other CPU finish storing its state
+ mov al, NotVacantFlag
+TryLock2:
+ db 0f0h ; opcode for lock instruction
+ xchg al, byte ptr [rdi]
+ cmp al, VacantFlag
+ jz LockObtained2
+ PAUSE32
+ jmp TryLock2
+
+LockObtained2:
+ mov bl, byte ptr [rdi + 1]
+ db 0f0h ; opcode for lock instruction
+ xchg al, byte ptr [rdi]
+ cmp bl, CPU_SWITCH_STATE_STORED
+ jb WaitForOtherStored
+
+ ; Since another CPU already stored its state, load them
+ ; load GDTR value
+ lgdt fword ptr [rdi + 16]
+
+ ; load IDTR value
+ lidt fword ptr [rdi + 26]
+
+ ; load its future StackPointer
+ mov rsp, qword ptr [rdi + 8]
+
+ ; update its switch state to LOADED
+ mov al, NotVacantFlag
+TryLock3:
+ db 0f0h ; opcode for lock instruction
+ xchg al, byte ptr [rsi]
+ cmp al, VacantFlag
+ jz LockObtained3
+ PAUSE32
+ jmp TryLock3
+
+LockObtained3:
+ mov byte ptr [rsi+1], CPU_SWITCH_STATE_LOADED
+ db 0f0h ; opcode for lock instruction
+ xchg al, byte ptr [rsi]
+
+WaitForOtherLoaded::
+ ; wait until the other CPU finish loading new state,
+ ; otherwise the data in stack may corrupt
+ mov al, NotVacantFlag
+TryLock4:
+ db 0f0h ; opcode for lock instruction
+ xchg al, byte ptr [rdi]
+ cmp al, VacantFlag
+ jz LockObtained4
+ PAUSE32
+ jmp TryLock4
+
+LockObtained4:
+ mov bl, byte ptr [rdi+1]
+ db 0f0h ; opcode for lock instruction
+ xchg al, byte ptr [rdi]
+ cmp bl, CPU_SWITCH_STATE_LOADED
+ jb WaitForOtherLoaded
+
+ ; since the other CPU already get the data it want, leave this procedure
+ popfq
+
+ pop rax
+ mov cr4, rax
+
+ pop rax
+ mov cr0, rax
+
+ pop r15
+ pop r14
+ pop r13
+ pop r12
+ pop r11
+ pop r10
+ pop r9
+ pop r8
+ pop rbp
+ pop rdi
+ pop rsi
+ pop rdx
+ pop rcx
+ pop rbx
+ pop rax
+
+ ret
+AsmExchangeRole ENDP
+
+GdtDesc QWORD 0
+ WORD 0
+
+IdtDesc QWORD 0
+ WORD 0
+
+text ENDS
+
+END
diff --git a/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/x64/PlatformCpuLib.h b/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/x64/PlatformCpuLib.h
new file mode 100644
index 0000000000..33fc064199
--- /dev/null
+++ b/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/x64/PlatformCpuLib.h
@@ -0,0 +1,135 @@
+/** @file
+ Library functions that can be called in both PEI and DXE phase.
+
+ Copyright (c) 2004 - 2015, 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 _PLATFORM_CPU_LIB_H_
+#define _PLATFORM_CPU_LIB_H_
+
+UINTN
+CpuReadCr0 (
+ VOID
+ );
+
+VOID
+CpuWriteCr0 (
+ UINTN Value
+ );
+
+UINTN
+CpuReadCr3 (
+ VOID
+ );
+
+VOID
+CpuWriteCr3 (
+ UINTN Value
+ );
+
+UINT8
+CpuMemRead8 (
+ IN EFI_PHYSICAL_ADDRESS Address
+ );
+
+UINT16
+CpuMemRead16 (
+ IN EFI_PHYSICAL_ADDRESS Address
+ );
+
+UINT32
+CpuMemRead32 (
+ IN EFI_PHYSICAL_ADDRESS Address
+ );
+
+UINT64
+CpuMemRead64 (
+ IN EFI_PHYSICAL_ADDRESS Address
+ );
+
+VOID
+CpuMemWrite8 (
+ IN EFI_PHYSICAL_ADDRESS Address,
+ IN UINT8 Data
+ );
+
+VOID
+CpuMemWrite16 (
+ IN EFI_PHYSICAL_ADDRESS Address,
+ IN UINT16 Data
+ );
+
+VOID
+CpuMemWrite32 (
+ IN EFI_PHYSICAL_ADDRESS Address,
+ IN UINT32 Data
+ );
+
+VOID
+CpuMemWrite64 (
+ IN EFI_PHYSICAL_ADDRESS Address,
+ IN UINT64 Data
+ );
+
+UINTN
+CpuSetPower2 (
+ IN UINTN Input
+ );
+
+UINT64
+CpuReadTsc (
+ VOID
+ );
+
+VOID
+CpuSwitchStacks (
+ IN UINTN EntryPoint,
+ IN UINTN Parameter,
+ IN UINTN NewStack,
+ IN UINTN NewBsp
+ );
+
+VOID
+CpuSwitchStacks2Args (
+ IN UINTN EntryPoint,
+ IN UINTN Parameter1,
+ IN UINTN Parameter2,
+ IN UINTN NewStack,
+ IN UINTN NewBsp
+ );
+
+UINT16
+CpuCodeSegment (
+ VOID
+ );
+
+VOID
+CpuBreak (
+ VOID
+ );
+
+VOID
+CpuLoadGlobalDescriptorTable (
+ VOID *Table16ByteAligned
+ );
+
+VOID
+CpuInitSelectors (
+ VOID
+ );
+
+VOID
+CpuLoadInterruptDescriptorTable (
+ VOID *Table16ByteAligned
+ );
+
+#endif
diff --git a/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/x64/ProcessorDef.h b/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/x64/ProcessorDef.h
new file mode 100644
index 0000000000..328a12fdd0
--- /dev/null
+++ b/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/x64/ProcessorDef.h
@@ -0,0 +1,57 @@
+/** @file
+ Definition for EM64T processor.
+
+ Copyright (c) 2004 - 2015, 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 _PROCESSOR_DEF_H
+#define _PROCESSOR_DEF_H
+
+#pragma pack(1)
+/**
+ @todo @todo add structure description
+
+**/
+typedef struct {
+ UINT16 Offset15To0;
+ UINT16 SegmentSelector;
+ UINT16 Attributes;
+ UINT16 Offset31To16;
+ UINT32 Offset63To32;
+ UINT32 Reserved;
+} INTERRUPT_GATE_DESCRIPTOR;
+
+#pragma pack()
+/**
+ @todo @todo add structure description
+
+**/
+typedef struct {
+ UINT8 *RendezvousFunnelAddress;
+ UINTN PModeEntryOffset;
+ UINTN FlatJumpOffset;
+ UINTN LModeEntryOffset;
+ UINTN LongJumpOffset;
+ UINTN Size;
+} MP_ASSEMBLY_ADDRESS_MAP;
+/**
+ Get address map of RendezvousFunnelProc.
+
+ @param[out] AddressMap - Output buffer for address map information
+
+**/
+VOID
+AsmGetAddressMap (
+ OUT MP_ASSEMBLY_ADDRESS_MAP *AddressMap
+ );
+
+#endif
diff --git a/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/x64/VirtualMemory.h b/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/x64/VirtualMemory.h
new file mode 100644
index 0000000000..e8ef0afc82
--- /dev/null
+++ b/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/CpuInit/x64/VirtualMemory.h
@@ -0,0 +1,147 @@
+/** @file
+ x64 Long Mode Virtual Memory Management Definitions.
+
+ References:
+ 1) IA-32 Intel(R) Atchitecture Software Developer's Manual Volume 1:Basic Architecture, Intel
+ 2) IA-32 Intel(R) Atchitecture Software Developer's Manual Volume 2:Instruction Set Reference, Intel
+ 3) IA-32 Intel(R) Atchitecture Software Developer's Manual Volume 3:System Programmer's Guide, Intel
+ 4) AMD64 Architecture Programmer's Manual Volume 2: System Programming
+
+ Copyright (c) 2004 - 2015, 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 _VIRTUAL_MEMORY_H_
+#define _VIRTUAL_MEMORY_H_
+
+#pragma pack(1)
+
+/**
+ Page-Map Level-4 Offset (PML4) and
+///Page-Directory-Pointer Offset (PDPE) entries 4K & 2MB
+
+**/
+typedef union {
+ struct {
+ UINT64 Present:1; // 0 = Not present in memory, 1 = Present in memory
+ UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write
+ UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User
+ UINT64 WriteThrough:1; // 0 = Write-Back caching, 1=Write-Through caching
+ UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached
+ UINT64 Accessed:1; // 0 = Not accessed, 1 = Accessed (set by CPU)
+ UINT64 Reserved:1; // Reserved
+ UINT64 MustBeZero:2; // Must Be Zero
+ UINT64 Available:3; // Available for use by system software
+ UINT64 PageTableBaseAddress:40; // Page Table Base Address
+ UINT64 AvabilableHigh:11; // Available for use by system software
+ UINT64 Nx:1; // No Execute bit
+ } Bits;
+ UINT64 Uint64;
+} x64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K;
+
+/**
+ Page-Directory Offset 4K
+
+**/
+typedef union {
+ struct {
+ UINT64 Present:1; // 0 = Not present in memory, 1 = Present in memory
+ UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write
+ UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User
+ UINT64 WriteThrough:1; // 0 = Write-Back caching, 1=Write-Through caching
+ UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached
+ UINT64 Accessed:1; // 0 = Not accessed, 1 = Accessed (set by CPU)
+ UINT64 Reserved:1; // Reserved
+ UINT64 MustBeZero:1; // Must Be Zero
+ UINT64 Reserved2:1; // Reserved
+ UINT64 Available:3; // Available for use by system software
+ UINT64 PageTableBaseAddress:40; // Page Table Base Address
+ UINT64 AvabilableHigh:11; // Available for use by system software
+ UINT64 Nx:1; // No Execute bit
+ } Bits;
+ UINT64 Uint64;
+} x64_PAGE_DIRECTORY_ENTRY_4K;
+
+/**
+ Page Table Entry 4K.
+
+**/
+typedef union {
+ struct {
+ UINT64 Present:1; // 0 = Not present in memory, 1 = Present in memory
+ UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write
+ UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User
+ UINT64 WriteThrough:1; // 0 = Write-Back caching, 1=Write-Through caching
+ UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached
+ UINT64 Accessed:1; // 0 = Not accessed, 1 = Accessed (set by CPU)
+ UINT64 Dirty:1; // 0 = Not Dirty, 1 = written by processor on access to page
+ UINT64 PAT:1; // 0 = Ignore Page Attribute Table
+ UINT64 Global:1; // 0 = Not global page, 1 = global page TLB not cleared on CR3 write
+ UINT64 Available:3; // Available for use by system software
+ UINT64 PageTableBaseAddress:40; // Page Table Base Address
+ UINT64 AvabilableHigh:11; // Available for use by system software
+ UINT64 Nx:1; // 0 = Execute Code, 1 = No Code Execution
+ } Bits;
+ UINT64 Uint64;
+} x64_PAGE_TABLE_ENTRY_4K;
+
+/**
+ Page Table Entry 2MB.
+
+**/
+typedef union {
+ struct {
+ UINT64 Present:1; // 0 = Not present in memory, 1 = Present in memory
+ UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write
+ UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User
+ UINT64 WriteThrough:1; // 0 = Write-Back caching, 1=Write-Through caching
+ UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached
+ UINT64 Accessed:1; // 0 = Not accessed, 1 = Accessed (set by CPU)
+ UINT64 Dirty:1; // 0 = Not Dirty, 1 = written by processor on access to page
+ UINT64 MustBe1:1; // Must be 1
+ UINT64 Global:1; // 0 = Not global page, 1 = global page TLB not cleared on CR3 write
+ UINT64 Available:3; // Available for use by system software
+ UINT64 PAT:1; //
+ UINT64 MustBeZero:8; // Must be zero;
+ UINT64 PageTableBaseAddress:31; // Page Table Base Address
+ UINT64 AvabilableHigh:11; // Available for use by system software
+ UINT64 Nx:1; // 0 = Execute Code, 1 = No Code Execution
+ } Bits;
+ UINT64 Uint64;
+} x64_PAGE_TABLE_ENTRY_2M;
+/**
+ @todo Add union description
+
+**/
+typedef union {
+ UINT64 Present:1; // 0 = Not present in memory, 1 = Present in memory
+ UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write
+ UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User
+ UINT64 WriteThrough:1; // 0 = Write-Back caching, 1=Write-Through caching
+ UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached
+ UINT64 Accessed:1; // 0 = Not accessed, 1 = Accessed (set by CPU)
+ UINT64 Dirty:1; // 0 = Not Dirty, 1 = written by processor on access to page
+ UINT64 Reserved:57;
+} x64_PAGE_TABLE_ENTRY_COMMON;
+/**
+ @todo Add union description
+
+**/
+typedef union {
+ x64_PAGE_TABLE_ENTRY_4K Page4k;
+ x64_PAGE_TABLE_ENTRY_2M Page2Mb;
+ x64_PAGE_TABLE_ENTRY_COMMON Common;
+} x64_PAGE_TABLE_ENTRY;
+
+
+#pragma pack()
+
+#endif