summaryrefslogtreecommitdiff
path: root/Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiMpServiceLib/Ia32
diff options
context:
space:
mode:
Diffstat (limited to 'Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiMpServiceLib/Ia32')
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiMpServiceLib/Ia32/MpEqu.h45
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiMpServiceLib/Ia32/MpEqu.inc49
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiMpServiceLib/Ia32/MpEquNasm.inc49
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiMpServiceLib/Ia32/MpFuncs.S316
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiMpServiceLib/Ia32/MpFuncs.asm365
-rw-r--r--Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiMpServiceLib/Ia32/MpFuncs.nasm361
6 files changed, 1185 insertions, 0 deletions
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiMpServiceLib/Ia32/MpEqu.h b/Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiMpServiceLib/Ia32/MpEqu.h
new file mode 100644
index 0000000000..df13a04a58
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiMpServiceLib/Ia32/MpEqu.h
@@ -0,0 +1,45 @@
+/** @file
+ This is the equates file for HT (Hyper-threading) support.
+
+ Copyright (c) 1999 - 2016, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#define VacantFlag 0x00
+#define NotVacantFlag 0xff
+
+#define LockLocation (0x1000 - 0x0400)
+#define StackStartAddressLocation (LockLocation + 0x04)
+#define StackSizeLocation (LockLocation + 0x08)
+#define CProcedureLocation (LockLocation + 0x0C)
+#define GdtrLocation (LockLocation + 0x10)
+#define IdtrLocation (LockLocation + 0x16)
+#define BufferStartLocation (LockLocation + 0x1C)
+#define PmodeOffsetLocation (LockLocation + 0x20)
+#define AcpiCpuDataAddressLocation (LockLocation + 0x24)
+#define MtrrValuesAddressLocation (LockLocation + 0x28)
+#define FinishedCountAddressLocation (LockLocation + 0x2C)
+#define WakeupCountAddressLocation (LockLocation + 0x30)
+#define SerializeLockAddressLocation (LockLocation + 0x34)
+#define MicrocodeAddressLocation (LockLocation + 0x38)
+#define BootScriptAddressLocation (LockLocation + 0x3C)
+#define StartStateLocation (LockLocation + 0x40)
+#define VirtualWireMode (LockLocation + 0x44)
+#define SemaphoreCheck (LockLocation + 0x48)
+#define PeiServices (LockLocation + 0x4C)
+#define PeiStall (LockLocation + 0x50)
+#define CpuPerfCtrlValue (LockLocation + 0x54)
+#define SiCpuPolicyPpi (LockLocation + 0x5C)
+#define MpSystemDataAddressLocation (LockLocation + 0x64)
+#define MpServicePpiAddressLocation (LockLocation + 0x68)
+#define CArgumentLocation (LockLocation + 0x6C)
+#define BistBufferLocation (LockLocation + 0x70)
+
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiMpServiceLib/Ia32/MpEqu.inc b/Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiMpServiceLib/Ia32/MpEqu.inc
new file mode 100644
index 0000000000..196019fefb
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiMpServiceLib/Ia32/MpEqu.inc
@@ -0,0 +1,49 @@
+;; @file
+; This is the equates file used in MpFuncs.asm, for MP support.
+;
+; Copyright (c) 1999 - 2016, Intel Corporation. All rights reserved.<BR>
+;
+; This program and the accompanying materials
+; are licensed and made available under the terms and conditions of the BSD License
+; which accompanies this distribution. The full text of the license may be found at
+; http://opensource.org/licenses/bsd-license.php.
+;
+; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED
+;
+;;
+
+VacantFlag Equ 00h
+NotVacantFlag Equ 0ffh
+
+LockLocation equ 1000h - 0400h
+StackStartAddressLocation equ LockLocation + 04h
+StackSizeLocation equ LockLocation + 08h
+CProcedureLocation equ LockLocation + 0Ch
+GdtrLocation equ LockLocation + 10h
+IdtrLocation equ LockLocation + 16h
+BufferStartLocation equ LockLocation + 1Ch
+PmodeOffsetLocation equ LockLocation + 20h
+AcpiCpuDataAddressLocation equ LockLocation + 24h
+MtrrValuesAddressLocation equ LockLocation + 28h
+FinishedCountAddressLocation equ LockLocation + 2Ch
+WakeupCountAddressLocation equ LockLocation + 30h
+SerializeLockAddressLocation equ LockLocation + 34h
+MicrocodeAddressLocation equ LockLocation + 38h
+BootScriptAddressLocation equ LockLocation + 3Ch
+StartStateLocation equ LockLocation + 40h
+VirtualWireMode equ LockLocation + 44h
+SemaphoreCheck equ LockLocation + 48h
+PeiServices equ LockLocation + 4Ch
+PeiStall equ LockLocation + 50h
+CpuPerfCtrlValue equ LockLocation + 54h
+SiCpuPolicyPpi equ LockLocation + 5Ch
+MpSystemDataAddressLocation equ LockLocation + 64h
+MpServicePpiAddressLocation equ LockLocation + 68h
+CArgumentLocation equ LockLocation + 6Ch
+BistBufferLocation equ LockLocation + 70h
+
+PAUSE32 MACRO
+ DB 0F3h
+ DB 090h
+ ENDM
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiMpServiceLib/Ia32/MpEquNasm.inc b/Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiMpServiceLib/Ia32/MpEquNasm.inc
new file mode 100644
index 0000000000..0590cd88de
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiMpServiceLib/Ia32/MpEquNasm.inc
@@ -0,0 +1,49 @@
+;; @file
+; This is the equates file used in MpFuncs.asm, for MP support.
+;
+; Copyright (c) 1999 - 2016, Intel Corporation. All rights reserved.<BR>
+;
+; This program and the accompanying materials
+; are licensed and made available under the terms and conditions of the BSD License
+; which accompanies this distribution. The full text of the license may be found at
+; http://opensource.org/licenses/bsd-license.php.
+;
+; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED
+;
+;;
+
+%define VacantFlag 0x0
+%define NotVacantFlag 0xff
+
+%define LockLocation 0x1000 - 0x400
+%define StackStartAddressLocation LockLocation + 0x4
+%define StackSizeLocation LockLocation + 0x8
+%define CProcedureLocation LockLocation + 0xC
+%define GdtrLocation LockLocation + 0x10
+%define IdtrLocation LockLocation + 0x16
+%define BufferStartLocation LockLocation + 0x1C
+%define PmodeOffsetLocation LockLocation + 0x20
+%define AcpiCpuDataAddressLocation LockLocation + 0x24
+%define MtrrValuesAddressLocation LockLocation + 0x28
+%define FinishedCountAddressLocation LockLocation + 0x2C
+%define WakeupCountAddressLocation LockLocation + 0x30
+%define SerializeLockAddressLocation LockLocation + 0x34
+%define MicrocodeAddressLocation LockLocation + 0x38
+%define BootScriptAddressLocation LockLocation + 0x3C
+%define StartStateLocation LockLocation + 0x40
+%define VirtualWireMode LockLocation + 0x44
+%define SemaphoreCheck LockLocation + 0x48
+%define PeiServices LockLocation + 0x4C
+%define PeiStall LockLocation + 0x50
+%define CpuPerfCtrlValue LockLocation + 0x54
+%define SiCpuPolicyPpi LockLocation + 0x5C
+%define MpSystemDataAddressLocation LockLocation + 0x64
+%define MpServicePpiAddressLocation LockLocation + 0x68
+%define CArgumentLocation LockLocation + 0x6C
+%define BistBufferLocation LockLocation + 0x70
+
+%macro PAUSE32 0
+ DB 0xF3
+ DB 0x90
+ %endmacro
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiMpServiceLib/Ia32/MpFuncs.S b/Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiMpServiceLib/Ia32/MpFuncs.S
new file mode 100644
index 0000000000..91ca56e85a
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiMpServiceLib/Ia32/MpFuncs.S
@@ -0,0 +1,316 @@
+## @file
+# This is the assembly code for MP support.
+#
+# Copyright (c) 1999 - 2016, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php.
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED
+#
+##
+
+#include "MpEqu.h"
+
+ .text
+ ASM_FUNCTION_REMOVE_IF_UNREFERENCED
+
+//-------------------------------------------------------------------------------
+// AsmAcquireMPLock (&Lock);
+//-------------------------------------------------------------------------------
+.globl ASM_PFX(AsmAcquireMPLock)
+ASM_PFX(AsmAcquireMPLock):
+
+ pusha
+ mov %esp, %ebp
+
+ mov $NotVacantFlag, %al
+ mov 0x24(%ebp), %ebx
+L_TryGetLock:
+ xchg (%ebx), %al
+ cmp $VacantFlag, %al
+ jz L_LockObtained
+
+ pause
+ jmp L_TryGetLock
+
+L_LockObtained:
+ popa
+ ret
+
+//-------------------------------------------------------------------------------
+// AsmReleaseMPLock (&Lock);
+//-------------------------------------------------------------------------------------
+.globl ASM_PFX(AsmReleaseMPLock)
+ASM_PFX(AsmReleaseMPLock):
+
+ pusha
+ mov %esp, %ebp
+
+ mov $VacantFlag, %al
+ movl 0x24(%ebp), %ebx
+ xchg (%ebx), %al
+
+ popa
+ ret
+
+//-------------------------------------------------------------------------------------
+//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);
+
+.globl ASM_PFX(RendezvousFunnelProc)
+ASM_PFX(RendezvousFunnelProc):
+L_RendezvousFunnelProcStart:
+
+ .code16
+
+// At this point CS = 0x(vv00) and ip= 0x0.
+ mov %eax, %ebp
+ mov %cs, %ax
+ mov %ax, %ds
+ mov %ax, %es
+ mov %ax, %ss
+ xor %ax, %ax
+ mov %ax, %fs
+ mov %ax, %gs
+
+// Get APIC ID
+ mov $1, %eax
+ cpuid
+ shr $24, %ebx
+ and $0xff, %ebx // EBX is APIC ID
+
+// If it is the first time AP wakes up, just record AP's BIST
+// Otherwise, switch to protected mode.
+
+ mov $StartStateLocation, %si
+ cmpl $0, (%si)
+ jnz L_SkipRecordBist
+
+// Record BIST information
+//
+ mov $8, %al
+ mul %bl
+ mov $BistBufferLocation, %si
+ add %ax, %si
+
+ movl $1, (%si) // Set Valid Flag
+ mov %ebp, 4(%si) // Store BIST value
+
+L_SkipRecordBist:
+// Switch to flat mode.
+
+ mov $BufferStartLocation, %si
+ mov (%si), %ebx
+
+ mov $PmodeOffsetLocation, %di
+ mov (%di), %eax
+ mov %ax, %di
+ sub $6, %di
+ add %ebx, %eax
+ mov %eax, (%di)
+
+ mov $0, %esi
+ mov $GdtrLocation, %si
+ lgdtl %cs:(%esi)
+
+ xor %ax, %ax
+ mov %ax, %ds
+
+ mov %cr0, %eax
+ or $0x00000003, %eax
+ mov %eax, %cr0
+
+ .byte 0x66, 0x67, 0xea // far jump
+ .long 0x00 // 32-bit offset
+ .short 0x20 // 16-bit selector
+
+ .code32
+L_NemInit: // protected mode entry point
+ mov $0x18, %ax
+ mov %ax, %ds
+ mov %ax, %es
+ mov %ax, %fs
+ mov %ax, %gs
+ mov %ax, %ss
+
+ mov %ebx, %esi
+
+ mov %esi, %edi
+ add $StartStateLocation, %edi
+ mov $1, %eax
+ movl %eax, (%edi)
+
+ mov %esi, %edi
+ add $LockLocation, %edi
+ mov $NotVacantFlag, %eax
+L_TestLock:
+ xchg %eax, (%edi)
+ cmp $NotVacantFlag, %eax
+ jz L_TestLock
+
+L_ProgramStack:
+
+ mov %esi, %edi
+ add $StackSizeLocation, %edi
+ mov (%edi), %eax
+ mov %esi, %edi
+ add $StackStartAddressLocation, %edi
+ add (%edi), %eax
+ mov %eax, %esp
+ movl %eax, (%edi)
+
+L_Releaselock:
+
+ mov $VacantFlag, %eax
+ mov %esi, %edi
+ add $LockLocation, %edi
+ xchg %eax, (%edi)
+
+L_CProcedureInvoke:
+
+ mov %esi, %edi
+ add $CArgumentLocation, %edi
+ mov (%edi), %eax
+ push %eax
+
+ mov %esi, %edi
+ add $CProcedureLocation, %edi
+ mov (%edi), %eax
+
+ call *%eax
+ add $4, %esp
+
+L_InterlockedIncrementFinishedCount:
+ mov %esi, %edi
+ add $FinishedCountAddressLocation, %edi
+ lock incl (%edi)
+
+1:
+ cli
+
+ hlt
+ jmp 1b
+
+
+//-------------------------------------------------------------------------------------
+// SemaphoreStartAddress
+//-------------------------------------------------------------------------------------
+
+L_SemaphoreStartAddress:
+ push %ebp
+ mov %esp, %ebp
+ mov 0x8(%ebp), %eax
+1:
+ cmpl $0, (%eax)
+ jz 1f
+
+ pause
+ jmp 1b
+
+1:
+ pop %ebp
+ ret
+
+//-------------------------------------------------------------------------------
+// AsmGetAddressMap
+//-------------------------------------------------------------------------------------
+.set L_NemInitOffset, L_NemInit - L_RendezvousFunnelProcStart
+.set L_SemaphoreOffset, L_SemaphoreStartAddress - L_RendezvousFunnelProcStart
+
+.globl ASM_PFX(AsmGetAddressMap)
+ASM_PFX(AsmGetAddressMap):
+ mov $L_RendezvousFunnelProcStart, %eax
+ ret
+
+
+//-------------------------------------------------------------------------------
+// AsmGetPmodeOffset
+//-------------------------------------------------------------------------------------
+.globl ASM_PFX(AsmGetPmodeOffset)
+ASM_PFX(AsmGetPmodeOffset):
+ mov $L_NemInitOffset, %eax
+ ret
+
+//-------------------------------------------------------------------------------
+// AsmGetSemaphoreCheckOffset
+//-------------------------------------------------------------------------------------
+.globl ASM_PFX(AsmGetSemaphoreCheckOffset)
+ASM_PFX(AsmGetSemaphoreCheckOffset):
+ mov $L_SemaphoreOffset, %eax
+ ret
+
+//-------------------------------------------------------------------------------------
+//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);
+//-------------------------------------------------------------------------------------
+#define CPU_SWITCH_STATE_IDLE 0
+#define CPU_SWITCH_STATE_STORED 1
+#define CPU_SWITCH_STATE_LOADED 2
+
+.globl 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.
+
+ pusha
+ mov %ebp, %esp
+
+
+ // esi contains MyInfo pointer
+ mov %ecx, %esi
+
+ // edi contains OthersInfo pointer
+ mov %edx, %edi
+
+ //Store EFLAGS, GDTR and IDTR regiter to stack
+ pushf
+ sgdt 8(%esi)
+ sidt 14(%esi)
+
+ // Store the its StackPointer
+ mov %esp, 4(%esi)
+
+ // update its switch state to STORED
+ movb $CPU_SWITCH_STATE_STORED, 1(%esi)
+ xchg %al, (%esi)
+
+L_WaitForOtherStored:
+ // wait until the other CPU finish storing its state
+ cmp $CPU_SWITCH_STATE_STORED, %edi
+ jb L_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
+ mov 4(%edi), %esp
+
+ // update its switch state to LOADED
+ movb $CPU_SWITCH_STATE_LOADED, 1(%edi)
+ xchg %al, (%edi)
+
+L_WaitForOtherLoaded:
+ // wait until the other CPU finish loading new state,
+ // otherwise the data in stack may corrupt
+ cmp $CPU_SWITCH_STATE_LOADED, %esi
+ jb L_WaitForOtherLoaded
+
+ // since the other CPU already get the data it want, leave this procedure
+ popf
+
+ popa
+ ret
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiMpServiceLib/Ia32/MpFuncs.asm b/Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiMpServiceLib/Ia32/MpFuncs.asm
new file mode 100644
index 0000000000..58a481d091
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiMpServiceLib/Ia32/MpFuncs.asm
@@ -0,0 +1,365 @@
+;; @file
+; This is the assembly code for MP support.
+;
+; Copyright (c) 1999 - 2016, Intel Corporation. All rights reserved.<BR>
+;
+; This program and the accompanying materials
+; are licensed and made available under the terms and conditions of the BSD License
+; which accompanies this distribution. The full text of the license may be found at
+; http://opensource.org/licenses/bsd-license.php.
+;
+; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED
+;
+;;
+
+include MpEqu.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);
+
+.686p
+.model flat
+.code
+
+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:
+ 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]
+ xchg al, byte ptr [ebx]
+
+ popad
+ ret
+AsmReleaseMPLock ENDP
+
+RendezvousFunnelProc PROC PUBLIC
+RendezvousFunnelProcStart::
+
+;Step-1: Grab a lock. 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 StartStateLocation ; mov si, StartState
+ db 66h, 83h, 3Ch, 00h ; cmp dword ptr [si], 0
+ db 75h ; opcode of jnz
+ db SkipRecordBist - ($ + 1) ; jnz SkipRecordBist
+
+; Record BIST information
+;
+ db 0B0h, 08h ; mov al, 8
+ db 0F6h, 0E3h ; mul bl
+
+ db 0BEh ; opcode of mov si, imm16
+ dw BistBufferLocation ; mov si, BistBufferLocation
+ 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
+
+SkipRecordBist::
+ db 0BEh ; opcode of mov si, mem16
+ dw BufferStartLocation ; mov si, BufferStartLocation
+ db 66h, 8Bh, 1Ch ; mov ebx,dword ptr [si]
+
+ db 0BFh ; opcode of mov di, mem16
+ dw PmodeOffsetLocation ; mov di, PmodeOffsetLocation
+ db 66h, 8Bh, 05h ; mov eax,dword ptr [di]
+ db 8Bh, 0F8h ; mov di, ax
+ db 83h, 0EFh,06h ; sub di, 06h
+ db 66h, 03h, 0C3h ; add eax, ebx
+ db 66h, 89h, 05h ; mov dword ptr [di],eax
+
+ db 0BEh ; opcode of mov si, mem16
+ dw GdtrLocation ; mov si, GdtrLocation
+ db 66h ; db 66h
+ db 2Eh, 0Fh, 01h, 14h ; lgdt fword ptr cs:[si]
+
+ db 0BEh ; opcode of mov si, mem16
+ dw IdtrLocation ; mov si, IdtrProfile
+ db 66h ; db 66h
+ db 2Eh, 0Fh, 01h, 1Ch ; lidt fword ptr cs:[si]
+
+ db 33h, 0C0h ; xor ax, ax
+ db 8Eh, 0D8h ; mov ds, ax
+
+ db 0Fh, 20h, 0C0h ; mov eax, cr0 ;Get control register 0
+ db 66h, 83h, 0C8h, 03h ; or eax, 000000003h ;Set PE bit (bit #0) & MP
+ db 0Fh, 22h, 0C0h ; mov cr0, eax
+
+ db 66h, 67h, 0EAh ; far jump
+ dd 0h ; 32-bit offset
+BspCS::
+ dw 00h ; 16-bit selector
+
+NemInit:: ; protected mode entry point
+
+ db 66h, 0B8h ; mov ax, 18h
+BspDS::
+ dw 00h
+ db 66h, 8Eh, 0D8h ; mov ds, ax
+ db 66h, 8Eh, 0C0h ; mov es, ax
+ db 66h, 8Eh, 0E0h ; mov fs, ax
+ db 66h, 8Eh, 0E8h ; mov gs, ax
+ db 66h, 8Eh, 0D0h ; mov ss, ax ; Flat mode setup.
+
+ mov esi, ebx
+
+ mov edi, esi
+ add edi, StartStateLocation
+ mov eax, 1
+ mov dword ptr [edi], eax
+
+ mov edi, esi
+ add edi, LockLocation
+ mov eax, NotVacantFlag
+TestLock::
+ xchg dword ptr [edi], eax
+ cmp eax, NotVacantFlag
+ jz TestLock
+
+ProgramStack::
+
+ mov edi, esi
+ add edi, StackSizeLocation
+ mov eax, dword ptr [edi]
+ mov edi, esi
+ add edi, StackStartAddressLocation
+ add eax, dword ptr [edi]
+ mov esp, eax
+ mov dword ptr [edi], eax
+
+Releaselock::
+
+ mov eax, VacantFlag
+ mov edi, esi
+ add edi, LockLocation
+ xchg dword ptr [edi], eax
+
+CProcedureInvoke::
+
+ mov edi, esi
+ add edi, CArgumentLocation
+ mov eax, dword ptr [edi]
+ push eax
+
+ mov edi, esi
+ add edi, CProcedureLocation
+ mov eax, dword ptr [edi]
+
+
+ push ecx
+ push eax
+ push edx
+
+ mov ecx, 0121h
+ rdmsr
+ test eax, eax
+ jnz SkipAcpiTimerWA
+ mov eax, 00010408h ; Bit 16 is enable and 15:0 address
+ mov edx, 2FBA2E25h
+ wrmsr
+SkipAcpiTimerWA:
+ pop edx
+ pop eax
+ pop ecx
+
+
+ call eax
+ add esp, 4
+
+InterlockedIncrementFinishedCount::
+ mov edi, esi
+ add edi, FinishedCountAddressLocation
+ lock inc dword ptr [edi]
+ cli
+ hlt
+ jmp $-2
+
+RendezvousFunnelProc ENDP
+
+SemaphoreStartAddress PROC C, SemaphoreAddress:PTR DWORD
+ mov eax, SemaphoreAddress
+@@:
+ cmp dword ptr [eax], 0
+ jz @F
+
+ PAUSE32
+ jmp @B
+@@:
+ ret
+SemaphoreStartAddress ENDP
+
+RendezvousFunnelProcEnd::
+
+
+;-------------------------------------------------------------------------------------
+; AsmGetAddressMap (&AddressMap);
+;-------------------------------------------------------------------------------------
+AsmGetAddressMap PROC near C PUBLIC
+
+ mov eax, RendezvousFunnelProcStart
+ ret
+
+AsmGetAddressMap ENDP
+
+AsmGetPmodeOffset PROC near C PUBLIC
+
+ mov eax, NemInit - RendezvousFunnelProcStart
+ ret
+
+AsmGetPmodeOffset ENDP
+
+AsmGetSemaphoreCheckOffset PROC near C PUBLIC
+ mov eax, SemaphoreStartAddress - RendezvousFunnelProcStart
+ ret
+AsmGetSemaphoreCheckOffset ENDP
+
+AsmPatchRendezvousCode PROC near C PUBLIC
+ mov eax, dword ptr [esp + 4]
+ push esi
+ push edi
+ mov edi, eax
+ mov ax, cs
+ mov esi, edi
+ add esi, BspCS - RendezvousFunnelProcStart
+ mov word ptr [esi], ax
+ mov ax, ds
+ mov esi, edi
+ add esi, BspDS - RendezvousFunnelProcStart
+ mov word ptr [esi], ax
+ pop edi
+ pop esi
+ xor eax, eax
+ ret
+AsmPatchRendezvousCode 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 byte ptr [esi], CPU_SWITCH_STATE_STORED
+
+WaitForOtherStored::
+ ; wait until the other CPU finish storing its state
+ cmp byte ptr [edi], CPU_SWITCH_STATE_STORED
+ jz OtherStored
+ PAUSE32
+ jmp WaitForOtherStored
+
+OtherStored::
+ ; 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 the other CPU's switch state to LOADED
+ mov byte ptr [edi], CPU_SWITCH_STATE_LOADED
+
+WaitForOtherLoaded::
+ ; wait until the other CPU finish loading new state,
+ ; otherwise the data in stack may corrupt
+ cmp byte ptr [esi], CPU_SWITCH_STATE_LOADED
+ jz OtherLoaded
+ PAUSE32
+ jmp WaitForOtherLoaded
+
+OtherLoaded::
+ ; since the other CPU already get the data it want, leave this procedure
+ popfd
+
+ popad
+ ret
+AsmExchangeRole ENDP
+
+END
+
diff --git a/Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiMpServiceLib/Ia32/MpFuncs.nasm b/Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiMpServiceLib/Ia32/MpFuncs.nasm
new file mode 100644
index 0000000000..deb580b6bb
--- /dev/null
+++ b/Silicon/BroxtonSoC/BroxtonSiPkg/Cpu/Library/Private/PeiMpServiceLib/Ia32/MpFuncs.nasm
@@ -0,0 +1,361 @@
+;; @file
+; This is the assembly code for MP support.
+;
+; Copyright (c) 2005 - 2016, Intel Corporation. All rights reserved.<BR>
+;
+; This program and the accompanying materials
+; are licensed and made available under the terms and conditions of the BSD License
+; which accompanies this distribution. The full text of the license may be found at
+; http://opensource.org/licenses/bsd-license.php.
+;
+; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED
+;
+;;
+
+%include "MpEquNasm.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);
+
+SECTION .text
+
+%macro PAUSE32 0
+ DB 0xF3
+ DB 0x90
+ %endmacro
+
+;-------------------------------------------------------------------------------
+; AsmAcquireMPLock (&Lock);
+;-------------------------------------------------------------------------------
+global ASM_PFX(AsmAcquireMPLock)
+ASM_PFX(AsmAcquireMPLock):
+
+ pushad
+ mov ebp,esp
+
+ mov al, NotVacantFlag
+ mov ebx, dword [ebp+0x24]
+L_TryGetLock:
+ xchg al, byte [ebx]
+ cmp al, VacantFlag
+ jz L_LockObtained
+
+ PAUSE32
+ jmp L_TryGetLock
+
+L_LockObtained:
+ popad
+ ret
+
+;-------------------------------------------------------------------------------
+; AsmReleaseMPLock (&Lock);
+;-------------------------------------------------------------------------------------
+global ASM_PFX(AsmReleaseMPLock)
+ASM_PFX(AsmReleaseMPLock):
+
+ pushad
+ mov ebp,esp
+
+ mov al, VacantFlag
+ mov ebx, dword [ebp+0x24]
+ xchg al, byte [ebx]
+
+ popad
+ ret
+
+global ASM_PFX(RendezvousFunnelProc)
+ASM_PFX(RendezvousFunnelProc):
+L_RendezvousFunnelProcStart:
+
+;Step-1: Grab a lock. At this point CS = 0x(vv00) and ip= 0x0.
+ db 0x66, 0x8b, 0xe8 ; mov ebp, eax
+ db 0x8c,0xc8 ; mov ax,cs
+ db 0x8e,0xd8 ; mov ds,ax
+ db 0x8e,0xc0 ; mov es,ax
+ db 0x8e,0xd0 ; mov ss,ax
+ db 0x33,0xc0 ; xor ax,ax
+ db 0x8e,0xe0 ; mov fs,ax
+ db 0x8e,0xe8 ; mov gs,ax
+; Get APIC ID
+;
+ db 0x66, 0xB8
+ dd 0x1 ; mov eax, 1
+ db 0xF, 0xA2 ; cpuid
+ db 0x66, 0xC1, 0xEB, 0x18 ; shr ebx, 24
+ db 0x66, 0x81, 0xE3
+ dd 0xFF ; 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 0xBE ; opcode of mov si, imm16
+ dw StartStateLocation ; mov si, StartState
+ db 0x66, 0x83, 0x3C, 0x0 ; cmp dword ptr [si], 0
+ db 0x75 ; opcode of jnz
+ db L_SkipRecordBist - ($ + 1) ; jnz SkipRecordBist
+
+; Record BIST information
+;
+ db 0xB0, 0x8 ; mov al, 8
+ db 0xF6, 0xE3 ; mul bl
+
+ db 0xBE ; opcode of mov si, imm16
+ dw BistBufferLocation ; mov si, BistBufferLocation
+ db 0x3, 0xF0 ; add si, ax
+
+ db 0x66, 0xC7, 0x4
+ dd 0x1 ; mov dword ptr [si], 1 ; Set Valid Flag
+ db 0x66, 0x89, 0x6C, 0x4 ; mov dword ptr [si + 4], ebp ; Store BIST value
+
+L_SkipRecordBist:
+ db 0xBE ; opcode of mov si, mem16
+ dw BufferStartLocation ; mov si, BufferStartLocation
+ db 0x66, 0x8B, 0x1C ; mov ebx,dword ptr [si]
+
+ db 0xBF ; opcode of mov di, mem16
+ dw PmodeOffsetLocation ; mov di, PmodeOffsetLocation
+ db 0x66, 0x8B, 0x5 ; mov eax,dword ptr [di]
+ db 0x8B, 0xF8 ; mov di, ax
+ db 0x83, 0xEF,0x6 ; sub di, 06h
+ db 0x66, 0x3, 0xC3 ; add eax, ebx
+ db 0x66, 0x89, 0x5 ; mov dword ptr [di],eax
+
+ db 0xBE ; opcode of mov si, mem16
+ dw GdtrLocation ; mov si, GdtrLocation
+ db 0x66 ; db 66h
+ db 0x2E, 0xF, 0x1, 0x14 ; lgdt fword ptr cs:[si]
+
+ db 0xBE ; opcode of mov si, mem16
+ dw IdtrLocation ; mov si, IdtrProfile
+ db 0x66 ; db 66h
+ db 0x2E, 0xF, 0x1, 0x1C ; lidt fword ptr cs:[si]
+
+ db 0x33, 0xC0 ; xor ax, ax
+ db 0x8E, 0xD8 ; mov ds, ax
+
+ db 0xF, 0x20, 0xC0 ; mov eax, cr0 ;Get control register 0
+ db 0x66, 0x83, 0xC8, 0x3 ; or eax, 000000003h ;Set PE bit (bit #0) & MP
+ db 0xF, 0x22, 0xC0 ; mov cr0, eax
+
+ db 0x66, 0x67, 0xEA ; far jump
+ dd 0x0 ; 32-bit offset
+BspCS:
+ dw 0x0 ; 16-bit selector
+
+L_NemInit: ; protected mode entry point
+
+ db 0x66, 0xB8 ; mov ax, 18h
+BspDS:
+ dw 0x0
+ db 0x66, 0x8E, 0xD8 ; mov ds, ax
+ db 0x66, 0x8E, 0xC0 ; mov es, ax
+ db 0x66, 0x8E, 0xE0 ; mov fs, ax
+ db 0x66, 0x8E, 0xE8 ; mov gs, ax
+ db 0x66, 0x8E, 0xD0 ; mov ss, ax ; Flat mode setup.
+
+ mov esi, ebx
+
+ mov edi, esi
+ add edi, StartStateLocation
+ mov eax, 1
+ mov dword [edi], eax
+
+ mov edi, esi
+ add edi, LockLocation
+ mov eax, NotVacantFlag
+L_TestLock:
+ xchg dword [edi], eax
+ cmp eax, NotVacantFlag
+ jz L_TestLock
+
+ProgramStack:
+
+ mov edi, esi
+ add edi, StackSizeLocation
+ mov eax, dword [edi]
+ mov edi, esi
+ add edi, StackStartAddressLocation
+ add eax, dword [edi]
+ mov esp, eax
+ mov dword [edi], eax
+
+L_Releaselock:
+
+ mov eax, VacantFlag
+ mov edi, esi
+ add edi, LockLocation
+ xchg dword [edi], eax
+
+L_CProcedureInvoke:
+
+ mov edi, esi
+ add edi, CArgumentLocation
+ mov eax, dword [edi]
+ push eax
+
+ mov edi, esi
+ add edi, CProcedureLocation
+ mov eax, dword [edi]
+
+;
+; reserved for SV_HOOKS START
+; itp.threads[n].msr(0x121, 0x2FBA2E2500010408)
+; WA for ACPI PM1 timer BXT 0 and 1
+ push ecx
+ push eax
+ push edx
+
+ mov ecx, 0x121
+ rdmsr
+ test eax, eax
+ jnz SkipAcpiTimerWA
+ mov eax, 0x10408 ; Bit 16 is enable and 15:0 address
+ mov edx, 0x2FBA2E25
+ wrmsr
+SkipAcpiTimerWA:
+ pop edx
+ pop eax
+ pop ecx
+;
+; Reserved for SV_HOOKS END
+
+ call eax
+ add esp, 4
+
+L_InterlockedIncrementFinishedCount:
+ mov edi, esi
+ add edi, FinishedCountAddressLocation
+ lock inc dword [edi]
+ cli
+ hlt
+ jmp $-2
+
+global ASM_PFX(SemaphoreStartAddress)
+ASM_PFX(SemaphoreStartAddress):
+ push ebp
+ mov ebp, esp
+ mov eax, dword [ebp + 0x8]
+.0:
+ cmp dword [eax], 0
+ jz .1
+
+ PAUSE32
+ jmp .0
+.1:
+ ret
+
+
+;-------------------------------------------------------------------------------------
+; AsmGetAddressMap (&AddressMap);
+;-------------------------------------------------------------------------------------
+global ASM_PFX(AsmGetAddressMap)
+ASM_PFX(AsmGetAddressMap):
+
+ mov eax, L_RendezvousFunnelProcStart
+ ret
+
+global ASM_PFX(AsmGetPmodeOffset)
+ASM_PFX(AsmGetPmodeOffset):
+
+ mov eax, L_NemInit - L_RendezvousFunnelProcStart
+ ret
+
+global ASM_PFX(AsmGetSemaphoreCheckOffset)
+ASM_PFX(AsmGetSemaphoreCheckOffset):
+ mov eax, SemaphoreStartAddress - L_RendezvousFunnelProcStart
+ ret
+
+global ASM_PFX(AsmPatchRendezvousCode)
+ASM_PFX(AsmPatchRendezvousCode):
+ mov eax, dword [esp + 4]
+ push esi
+ push edi
+ mov edi, eax
+ mov ax, cs
+ mov esi, edi
+ add esi, BspCS - L_RendezvousFunnelProcStart
+ mov word [esi], ax
+ mov ax, ds
+ mov esi, edi
+ add esi, BspDS - L_RendezvousFunnelProcStart
+ mov word [esi], ax
+ pop edi
+ pop esi
+ xor eax, eax
+ ret
+
+;-------------------------------------------------------------------------------------
+;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);
+;-------------------------------------------------------------------------------------
+%define CPU_SWITCH_STATE_IDLE 0
+%define CPU_SWITCH_STATE_STORED 1
+%define CPU_SWITCH_STATE_LOADED 2
+
+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.
+ pushad
+ mov ebp,esp
+
+ ; esi contains MyInfo pointer
+ mov esi, dword [ebp+0x24]
+
+ ; edi contains OthersInfo pointer
+ mov edi, dword [ebp+0x28]
+
+ ;Store EFLAGS, GDTR and IDTR regiter to stack
+ pushfd
+ sgdt [esi+8]
+ sidt [esi+14]
+
+ ; Store the its StackPointer
+ mov dword [esi+4],esp
+
+ ; update its switch state to STORED
+ mov byte [esi], CPU_SWITCH_STATE_STORED
+
+L_WaitForOtherStored:
+ ; wait until the other CPU finish storing its state
+ cmp byte [edi], CPU_SWITCH_STATE_STORED
+ jz L_OtherStored
+ PAUSE32
+ jmp L_WaitForOtherStored
+
+L_OtherStored:
+ ; Since another CPU already stored its state, load them
+ ; load GDTR value
+ lgdt [edi+8]
+
+ ; load IDTR value
+ lidt [edi+14]
+
+ ; load its future StackPointer
+ mov esp, dword [edi+4]
+
+ ; update the other CPU's switch state to LOADED
+ mov byte [edi], CPU_SWITCH_STATE_LOADED
+
+L_WaitForOtherLoaded:
+ ; wait until the other CPU finish loading new state,
+ ; otherwise the data in stack may corrupt
+ cmp byte [esi], CPU_SWITCH_STATE_LOADED
+ jz L_OtherLoaded
+ PAUSE32
+ jmp L_WaitForOtherLoaded
+
+L_OtherLoaded:
+ ; since the other CPU already get the data it want, leave this procedure
+ popfd
+
+ popad
+ ret