summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGuo Mang <mang.guo@intel.com>2016-06-02 13:09:54 +0800
committerHao Wu <hao.a.wu@intel.com>2016-06-07 09:55:22 +0800
commit6c272b873425166c7c090bc075f531f0322e5f6a (patch)
tree2e76daa7c69dc11c8e15f442c3a79716e3df1d5f
parent2f4cd8bb806bdafa830c730105c3cf48ff412a55 (diff)
downloadedk2-platforms-6c272b873425166c7c090bc075f531f0322e5f6a.tar.xz
ChvRefCodePkg: Add CPU S3 code.
Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Guo Mang <mang.guo@intel.com>
-rw-r--r--ChvRefCodePkg/CherryViewSoc/CPU/CpuS3/CpuAsm.asm143
-rw-r--r--ChvRefCodePkg/CherryViewSoc/CPU/CpuS3/CpuAsm.s137
-rw-r--r--ChvRefCodePkg/CherryViewSoc/CPU/CpuS3/HtFuncs.asm161
-rw-r--r--ChvRefCodePkg/CherryViewSoc/CPU/CpuS3/HtFuncs.s175
-rw-r--r--ChvRefCodePkg/CherryViewSoc/CPU/CpuS3/Htequ.inc41
-rw-r--r--ChvRefCodePkg/CherryViewSoc/CPU/CpuS3/Microcode.c311
-rw-r--r--ChvRefCodePkg/CherryViewSoc/CPU/CpuS3/MpCommon.h210
-rw-r--r--ChvRefCodePkg/CherryViewSoc/CPU/CpuS3/MpS3.c678
-rw-r--r--ChvRefCodePkg/CherryViewSoc/CPU/CpuS3/MpS3.inf50
-rw-r--r--ChvRefCodePkg/CherryViewSoc/CPU/CpuS3/MtrrSync.c239
10 files changed, 2145 insertions, 0 deletions
diff --git a/ChvRefCodePkg/CherryViewSoc/CPU/CpuS3/CpuAsm.asm b/ChvRefCodePkg/CherryViewSoc/CPU/CpuS3/CpuAsm.asm
new file mode 100644
index 0000000000..30cd5c205f
--- /dev/null
+++ b/ChvRefCodePkg/CherryViewSoc/CPU/CpuS3/CpuAsm.asm
@@ -0,0 +1,143 @@
+;; @file
+; This is the code that supports IA32 CPU architectural protocol
+;
+; 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
+;
+;;
+
+include Htequ.inc
+
+.686p
+.model flat
+.code
+
+PAUSE32 MACRO
+ DB 0F3h
+ DB 090h
+ ENDM
+
+EnableMCE proc near C public
+
+ mov eax, cr4
+ or eax, 40h
+ mov cr4, eax
+
+ ret
+
+EnableMCE endp
+
+MpMtrrSynchUpEntry PROC NEAR C 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 C 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
+
+;-------------------------------------------------------------------------------
+; 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
+
+CpuPause PROC NEAR C PUBLIC
+
+ PAUSE32
+ ret
+
+CpuPause ENDP
+
+END
diff --git a/ChvRefCodePkg/CherryViewSoc/CPU/CpuS3/CpuAsm.s b/ChvRefCodePkg/CherryViewSoc/CPU/CpuS3/CpuAsm.s
new file mode 100644
index 0000000000..8a973e785d
--- /dev/null
+++ b/ChvRefCodePkg/CherryViewSoc/CPU/CpuS3/CpuAsm.s
@@ -0,0 +1,137 @@
+## @file
+#
+# This is the code that supports IA32 CPU architectural protocol.
+#
+# 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
+#
+##
+.equ VacantFlag, 0x00
+.equ NotVacantFlag, 0x0ff
+
+.equ LockLocation, 0x1000 - 0x0200
+.equ StackStartAddressLocation, LockLocation + 0x04
+.equ StackSizeLocation, LockLocation + 0x08
+.equ CProcedureLocation, LockLocation + 0x0C
+.equ GdtrLocation, LockLocation + 0x10
+.equ IdtrLocation, LockLocation + 0x16
+.equ BufferStartLocation, LockLocation + 0x1C
+.equ PmodeOffsetLocation, LockLocation + 0x20
+.equ AcpiCpuDataAddressLocatio, LockLocation + 0x24
+.equ MtrrValuesAddressLocation, LockLocation + 0x28
+.equ FinishedCountAddressLocation, LockLocation + 0x2C
+.equ SerializeLockAddressLocation, LockLocation + 0x30
+.equ MicrocodeAddressLocation, LockLocation + 0x34
+.equ BootScriptAddressLocation, LockLocation + 0x38
+.equ StartStateLocation, LockLocation + 0x3C
+
+
+ASM_GLOBAL ASM_PFX(EnableMCE)
+ASM_PFX(EnableMCE):
+ movl %cr4, %eax
+ orl $0x40, %eax
+ movl %eax, %cr4
+ ret
+#EnableMCE endp
+
+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
+
+#-------------------------------------------------------------------------------
+# 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
+
+ .byte 0xf3, 0x90 # 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
diff --git a/ChvRefCodePkg/CherryViewSoc/CPU/CpuS3/HtFuncs.asm b/ChvRefCodePkg/CherryViewSoc/CPU/CpuS3/HtFuncs.asm
new file mode 100644
index 0000000000..3d5a9fa203
--- /dev/null
+++ b/ChvRefCodePkg/CherryViewSoc/CPU/CpuS3/HtFuncs.asm
@@ -0,0 +1,161 @@
+;; @file
+;
+; This is the equates file for HT (Hyper-threading) support
+;
+; 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
+;
+;;
+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);
+
+.686p
+.model flat
+.code
+
+
+RendezvousFunnelProc PROC PUBLIC
+RendezvousFunnelProcStart::
+
+;Step-1: Grab a lock. At this point CS = 0x(vv00) and ip= 0x0.
+
+ db 8ch,0c8h ; mov ax,cs
+ db 8eh,0d8h ; mov ds,ax
+ db 8eh,0c0h ; mov es,ax
+ db 8eh,0d0h ; mov ss,ax
+ db 33h,0c0h ; xor ax,ax
+ db 8eh,0e0h ; mov fs,ax
+ db 8eh,0e8h ; mov gs,ax
+
+ db 0BEh, 1Ch, 0Eh ; mov si, BufferStartLocation
+ db 66h, 8Bh, 1Ch ; mov ebx,dword ptr [si]
+
+ db 0BFh, 20h, 0Eh ; 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, 10h, 0Eh ; mov si, GdtrProfile
+ db 66h ; db 66h
+ db 2Eh, 0Fh, 01h, 14h ; lgdt fword ptr cs:[si]
+
+ db 33h, 0C0h ; xor ax, ax
+ db 8Eh, 0D8h ; mov ds, ax
+
+ db 0Fh, 20h, 0C0h ; mov eax, cr0 ;Get control register 0
+ db 66h, 83h, 0C8h, 03h ; or eax, 000000003h ;Set PE bit (bit #0) & MP
+ db 0Fh, 22h, 0C0h ; mov cr0, eax
+
+ db 66h, 67h, 0EAh ; far jump
+ dd 0h ; 32-bit offset
+ dw 20h ; 16-bit selector
+
+NemInit:: ; protected mode entry point
+
+ db 66h, 0B8h, 18h, 00h ; mov ax, 18h
+ db 66h, 8Eh, 0D8h ; mov ds, ax
+ db 66h, 8Eh, 0C0h ; mov es, ax
+ db 66h, 8Eh, 0E0h ; mov fs, ax
+ db 66h, 8Eh, 0E8h ; mov gs, ax
+ db 66h, 8Eh, 0D0h ; mov ss, ax ; Flat mode setup.
+
+ mov esi, ebx
+
+ mov edi, esi
+ add edi, StartStateLocation
+ mov eax, 1
+ mov dword ptr [edi], eax
+
+ mov edi, esi
+ add edi, LockLocation
+ mov eax, NotVacantFlag
+TestLock::
+ xchg dword ptr [edi], eax
+ cmp eax, NotVacantFlag
+ jz TestLock
+
+ProgramStack::
+
+ mov edi, esi
+ add edi, StackSizeLocation
+ mov eax, dword ptr [edi]
+ mov edi, esi
+ add edi, StackStartAddressLocation
+ add eax, dword ptr [edi]
+ mov esp, eax
+ mov dword ptr [edi], eax
+
+Releaselock::
+
+ mov eax, VacantFlag
+ mov edi, esi
+ add edi, LockLocation
+ xchg dword ptr [edi], eax
+
+CProcedureInvoke::
+
+ mov edi, esi
+ add edi, MtrrValuesAddressLocation
+ mov eax, dword ptr [edi]
+ push eax
+
+ mov eax, esi
+ add eax, LockLocation
+ push eax
+
+ mov edi, esi
+ add edi, CProcedureLocation
+ mov eax, dword ptr [edi]
+
+ call eax
+ add esp, 8
+
+ cli
+ hlt
+ jmp $-2
+
+RendezvousFunnelProc 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
+
+AsmCliHltLoop PROC near C PUBLIC
+ cli
+ hlt
+ jmp $-2
+AsmCliHltLoop ENDP
+
+END
diff --git a/ChvRefCodePkg/CherryViewSoc/CPU/CpuS3/HtFuncs.s b/ChvRefCodePkg/CherryViewSoc/CPU/CpuS3/HtFuncs.s
new file mode 100644
index 0000000000..a8a0686040
--- /dev/null
+++ b/ChvRefCodePkg/CherryViewSoc/CPU/CpuS3/HtFuncs.s
@@ -0,0 +1,175 @@
+## @file
+# This is the assembly code for HT (Hyper-threading) support
+#
+# 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
+#
+##
+.equ VacantFlag, 0x00
+.equ NotVacantFlag, 0x0ff
+
+.equ LockLocation, 0x1000 - 0x0200
+.equ StackStartAddressLocation, LockLocation + 0x04
+.equ StackSizeLocation, LockLocation + 0x08
+.equ CProcedureLocation, LockLocation + 0x0C
+.equ GdtrLocation, LockLocation + 0x10
+.equ IdtrLocation, LockLocation + 0x16
+.equ BufferStartLocation, LockLocation + 0x1C
+.equ PmodeOffsetLocation, LockLocation + 0x20
+.equ AcpiCpuDataAddressLocatio, LockLocation + 0x24
+.equ MtrrValuesAddressLocation, LockLocation + 0x28
+.equ FinishedCountAddressLocation, LockLocation + 0x2C
+.equ SerializeLockAddressLocation, LockLocation + 0x30
+.equ MicrocodeAddressLocation, LockLocation + 0x34
+.equ BootScriptAddressLocation, LockLocation + 0x38
+.equ StartStateLocation, LockLocation + 0x3C
+
+#-------------------------------------------------------------------------------------
+#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:
+
+#Step-1: Grab a lock. At this point CS = 0x(vv00) and ip= 0x0.
+ .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
+
+ .byte 0xBE, 0x1C, 0x0E # mov si, BufferStartLocation
+ .byte 0x66, 0x8B, 0x1C # mov ebx,dword ptr [si]
+
+ .byte 0xBF, 0x20, 0x0E # mov di, PmodeOffsetLocation
+ .byte 0x66, 0x8B, 0x05 # mov eax,dword ptr [di]
+ .byte 0x8B, 0xF8 # mov di, ax
+ .byte 0x83, 0xEF, 0x06 # sub di, 06h
+ .byte 0x66, 0x03, 0xC3 # add eax, ebx
+ .byte 0x66, 0x89, 0x05 # mov dword ptr [di],eax
+
+ .byte 0xBE, 0x10, 0x0E # mov si, GdtrProfile
+ .byte 0x66 # db 66h
+ .byte 0x2E, 0x0F, 0x01, 0x14 # lgdt 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, 0x03 # or eax, 000000003h #Set PE bit (bit #0) & MP
+ .byte 0x0F, 0x22, 0xC0 # mov cr0, eax
+
+ .byte 0x66, 0x67, 0xEA # far jump
+ .word 0x0, 0x0 # 32-bit offset
+ .word 0x20 # 16-bit selector
+
+NemInit: # protected mode entry point
+
+ .byte 0x66, 0xB8, 0x18, 0x00 # mov ax, 18h
+ .byte 0x66, 0x8E, 0xD8 # mov ds, ax
+ .byte 0x66, 0x8E, 0xC0 # mov es, ax
+ .byte 0x66, 0x8E, 0xE0 # mov fs, ax
+ .byte 0x66, 0x8E, 0xE8 # mov gs, ax
+ .byte 0x66, 0x8E, 0xD0 # mov ss, ax # Flat mode setup.
+
+ movl %ebx, %esi
+
+ movl %esi, %edi
+ addl $StartStateLocation, %edi
+ movl $1, %eax
+ movl %eax, (%edi)
+
+ movl %esi, %edi
+ addl $LockLocation, %edi
+ movl $NotVacantFlag, %eax
+TestLock:
+ xchgl %eax, (%edi)
+ cmpl $NotVacantFlag, %eax
+ jz TestLock
+
+ProgramStack:
+
+ movl %esi, %edi
+ addl $StackSizeLocation, %edi
+ movl (%edi), %eax
+ movl %esi, %edi
+ addl $StackStartAddressLocation, %edi
+ addl (%edi), %eax
+ movl %eax, %esp
+ movl %eax, (%edi)
+
+Releaselock:
+
+ movl $VacantFlag, %eax
+ movl %esi, %edi
+ addl $LockLocation, %edi
+ xchgl %eax, (%edi)
+
+CProcedureInvoke:
+
+ movl %esi, %edi
+ addl $MtrrValuesAddressLocation, %edi
+ movl (%edi), %eax
+ push %eax
+
+ movl %esi, %eax
+ addl $LockLocation, %eax
+ push %eax
+
+ movl %esi, %edi
+ addl $CProcedureLocation, %edi
+ movl (%edi), %eax
+
+ call %eax
+ addl $8, %esp
+
+ cli
+ hlt
+ jmp .-2
+
+#RendezvousFunnelProc ENDP
+RendezvousFunnelProcEnd:
+
+
+#-------------------------------------------------------------------------------------
+# AsmGetAddressMap (&AddressMap)
+#-------------------------------------------------------------------------------------
+ASM_GLOBAL ASM_PFX(AsmGetAddressMap)
+ASM_PFX(AsmGetAddressMap):
+
+ movl $RendezvousFunnelProcStart, %eax
+ ret
+
+#AsmGetAddressMap ENDP
+
+ASM_GLOBAL ASM_PFX(AsmGetPmodeOffset)
+ASM_PFX(AsmGetPmodeOffset):
+
+
+ movl $NemInit, %eax
+ subl $RendezvousFunnelProcStart, %eax
+ ret
+
+#AsmGetPmodeOffset ENDP
+
+ASM_GLOBAL ASM_PFX(AsmCliHltLoop)
+ASM_PFX(AsmCliHltLoop):
+ cli
+ hlt
+ jmp .-2
+#AsmCliHltLoop ENDP
diff --git a/ChvRefCodePkg/CherryViewSoc/CPU/CpuS3/Htequ.inc b/ChvRefCodePkg/CherryViewSoc/CPU/CpuS3/Htequ.inc
new file mode 100644
index 0000000000..5ec0137311
--- /dev/null
+++ b/ChvRefCodePkg/CherryViewSoc/CPU/CpuS3/Htequ.inc
@@ -0,0 +1,41 @@
+;; @file
+;
+; This is the equates file for HT (Hyper-threading) support
+;
+; 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
+
+LockLocation equ 1000h - 0200h
+StackStartAddressLocation equ LockLocation + 04h
+StackSizeLocation equ LockLocation + 08h
+CProcedureLocation equ LockLocation + 0Ch
+GdtrLocation equ LockLocation + 10h
+IdtrLocation equ LockLocation + 16h
+BufferStartLocation equ LockLocation + 1Ch
+PmodeOffsetLocation equ LockLocation + 20h
+AcpiCpuDataAddressLocation equ LockLocation + 24h
+MtrrValuesAddressLocation equ LockLocation + 28h
+FinishedCountAddressLocation equ LockLocation + 2Ch
+SerializeLockAddressLocation equ LockLocation + 30h
+MicrocodeAddressLocation equ LockLocation + 34h
+BootScriptAddressLocation equ LockLocation + 38h
+StartStateLocation equ LockLocation + 3Ch
+
+PAUSE32 MACRO
+ DB 0F3h
+ DB 090h
+ ENDM
+
+;-------------------------------------------------------------------------------
diff --git a/ChvRefCodePkg/CherryViewSoc/CPU/CpuS3/Microcode.c b/ChvRefCodePkg/CherryViewSoc/CPU/CpuS3/Microcode.c
new file mode 100644
index 0000000000..40feaf4fec
--- /dev/null
+++ b/ChvRefCodePkg/CherryViewSoc/CPU/CpuS3/Microcode.c
@@ -0,0 +1,311 @@
+/** @file
+ Functions for loading 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 "MpCommon.h"
+
+//
+// Array of pointers which each points to 1 microcode update binary (in memory)
+//
+EFI_CPU_MICROCODE_HEADER **mMicrocodePointerBuffer;
+
+//
+// Function declarations
+//
+EFI_STATUS
+FindLoadMicrocode (
+ IN UINT32 Cpuid,
+ IN EFI_CPU_MICROCODE_HEADER **MicrocodePointerBuffer,
+ IN OUT UINT32 *Revision,
+ IN OUT BOOLEAN *VerifyMicrocodeChecksum
+ );
+
+#ifdef __GNUC__ // GCC compiler
+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);
+}
+#else // MSFT compiler
+
+/**
+
+ @todo add description
+
+**/
+UINT32
+GetCpuUcodeRevision (
+ VOID
+ )
+{
+ UINT32 registers[4];
+ __writemsr (EFI_MSR_IA32_BIOS_SIGN_ID, 0);
+ __cpuid (registers, EFI_CPUID_VERSION_INFO);
+ return (UINT32) (__readmsr (EFI_MSR_IA32_BIOS_SIGN_ID) >> 32);
+}
+#endif
+
+/**
+
+ 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)
+
+ FailedRevision - The microcode revision that fails to be loaded
+
+ @retval
+
+ EFI_SUCCESS - A new microcode update is loaded
+ 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,
+ IN OUT BOOLEAN *VerifyMicrocodeChecksum
+ )
+
+{
+ EFI_STATUS Status;
+ UINT32 UcodeRevision;
+ UINT32 RegEax;
+
+ AsmCpuid (EFI_CPUID_VERSION_INFO, &RegEax, NULL, NULL, NULL);
+
+ if (IsBsp) {
+ //
+ // Force Microcode to be loaded for BSP anyway
+ //
+ UcodeRevision = 0;
+ } else {
+ UcodeRevision = GetCpuUcodeRevision ();
+ }
+
+ Status = FindLoadMicrocode (RegEax, MicrocodePointerBuffer, &UcodeRevision, VerifyMicrocodeChecksum);
+ *FailedRevision = UcodeRevision;
+ return Status;
+}
+
+/**
+
+ This will load the microcode to all the processors.
+
+ @param[in]
+ MicrocodeEntryPoint - The microcode update pointer
+ Revision - The current (before load this microcode update) microcode revision
+
+ @retval
+
+ EFI_SUCCESS - Microcode loaded
+ 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] 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,
+ IN OUT BOOLEAN *VerifyMicrocodeChecksum
+ )
+
+{
+ EFI_STATUS Status;
+ EFI_CPU_MICROCODE_HEADER *MicrocodeEntryPoint;
+ UINT8 Index;
+ UINT8 MsrPlatform;
+ UINT32 ExtendedTableLength;
+ UINT32 ExtendedTableCount;
+ BOOLEAN CorrectMicrocode;
+ EFI_CPU_MICROCODE_EXTENDED_TABLE *ExtendedTable;
+ EFI_CPU_MICROCODE_EXTENDED_TABLE_HEADER *ExtendedTableHeader;
+ UINT8 IndexStep;
+
+ 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));
+
+ IndexStep = (UINT32) (MicrocodePointerBuffer [1]) == 0 ? 2 : 1;
+
+ 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 (*VerifyMicrocodeChecksum == 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)) {
+ *VerifyMicrocodeChecksum = 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 (Index = 0; Index < ExtendedTableCount; Index ++) {
+ 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;
+ }
+ }
+
+ //
+ // Increase table index, 32-bit : 1, 64-bit : 2
+ //
+ Index += IndexStep;
+
+ }
+
+ return Status;
+}
diff --git a/ChvRefCodePkg/CherryViewSoc/CPU/CpuS3/MpCommon.h b/ChvRefCodePkg/CherryViewSoc/CPU/CpuS3/MpCommon.h
new file mode 100644
index 0000000000..ec5f73cdd7
--- /dev/null
+++ b/ChvRefCodePkg/CherryViewSoc/CPU/CpuS3/MpCommon.h
@@ -0,0 +1,210 @@
+/** @file
+ 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 <PiPei.h>
+#include <Guid/AcpiVariableCompatibility.h>
+#include <Ppi/Stall.h>
+#include <Ppi/SmmAccess.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PeiServicesLib.h>
+#include "../Include/CpuRegs.h"
+#include "../Include/CpuDataStruct.h"
+
+
+#define TRIGGER_MODE_EDGE 0x0
+#define TRIGGER_MODE_LEVEL 0x1
+#define DELIVERY_MODE_INIT 0x5
+#define DELIVERY_MODE_SIPI 0x6
+
+#define VacantFlag 0x00
+#define NotVacantFlag 0xff
+
+#define MICROSECOND 10
+
+#define MAXIMUM_CPU_NUMBER 0x40
+#define STACK_SIZE_PER_PROC 0x8000
+
+#define MAXIMUM_CPU_S3_TABLE_SIZE 0x1000
+
+#define IO_APIC_INDEX_REGISTER 0xFEC00000
+#define IO_APIC_DATA_REGISTER 0xFEC00010
+
+extern UINTN FixedMtrrNumber;
+extern UINTN MtrrDefTypeNumber;
+extern UINTN VariableMtrrNumber;
+
+/**
+
+ @todo add description
+
+**/
+typedef struct {
+ UINT8 APSerializeLock;
+
+ UINT8 Tm2Core2BusRatio;
+ UINT8 Tm2Vid;
+ BOOLEAN LimitCpuidMaximumValue;
+ BOOLEAN IsC1eSupported;
+ BOOLEAN IsXapicSupported;
+ BOOLEAN IsCCxSupported;
+
+ UINT32 ApicID[MAXIMUM_CPU_NUMBER];
+
+ UINT64 NumberOfCPUs;
+ UINT64 NumberOfEnabledCPUs;
+ UINT64 MaximumCPUsForThisSystem;
+
+ UINTN mFinishedCount;
+} HT_SYSTEM_DATA;
+
+/**
+
+ @todo add description
+
+**/
+typedef struct {
+ UINT16 Index;
+ UINT64 Value;
+} EFI_MTRR_VALUES;
+
+/**
+
+ @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
+
+**/
+typedef struct {
+ UINT32 Lock;
+ UINT32 StackStart;
+ UINT32 StackSize;
+ UINT32 ApFunction;
+ IA32_DESCRIPTOR GdtrProfile;
+ IA32_DESCRIPTOR IdtrProfile;
+ UINT32 BufferStart;
+ UINT32 PmodeOffset;
+ UINT32 AcpiCpuDataAddress;
+ UINT32 MtrrValuesAddress;
+ UINT32 FinishedCount;
+ UINT32 SerializeLock;
+ UINT32 MicrocodePointer;
+ MP_CPU_S3_SCRIPT_DATA *S3BootScriptTable;
+ UINT32 StartState;
+ UINT32 VirtualWireMode;
+ BOOLEAN VerifyMicrocodeChecksum;
+} MP_CPU_EXCHANGE_INFO;
+
+VOID *
+AsmGetPmodeOffset (
+ );
+
+VOID
+ReadMtrrRegisters (
+ UINT64 *MtrrValues
+ );
+
+VOID
+MpMtrrSynchUp (
+ UINT64 *MtrrValues
+ );
+
+VOID
+SetBspMtrrRegisters (
+ IN EFI_MTRR_VALUES *MtrrArray
+ );
+
+EFI_STATUS
+InitializeMicrocode (
+ IN EFI_CPU_MICROCODE_HEADER **MicrocodePointerBuffer,
+ OUT UINT32 *FailedRevision,
+ IN BOOLEAN IsBsp,
+ IN OUT BOOLEAN *VerifyMicrocodeChecksum
+ );
+
+//
+// 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,
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_STALL_PPI *PeiStall
+ );
+
+UINT32
+GetApicID (
+ VOID
+ );
+
+VOID
+ProgramVirtualWireMode (
+ BOOLEAN BSP,
+ UINT32 VirtualWireMode
+ );
+
+VOID
+AsmAcquireMPLock (
+ IN UINT8 *Lock
+ );
+
+VOID
+AsmReleaseMPLock (
+ IN UINT8 *Lock
+ );
+
+VOID *
+AsmGetAddressMap (
+ );
+
+VOID
+AsmCliHltLoop (
+ );
+
+VOID
+CpuPause (
+ VOID
+ );
+
+#endif
diff --git a/ChvRefCodePkg/CherryViewSoc/CPU/CpuS3/MpS3.c b/ChvRefCodePkg/CherryViewSoc/CPU/CpuS3/MpS3.c
new file mode 100644
index 0000000000..94fe13f0ef
--- /dev/null
+++ b/ChvRefCodePkg/CherryViewSoc/CPU/CpuS3/MpS3.c
@@ -0,0 +1,678 @@
+/** @file
+ Cpu driver running on S3 boot path.
+
+ 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"
+
+EFI_GUID mSmramCpuNvsHeaderGuid = EFI_SMRAM_CPU_NVS_HEADER_GUID;
+
+/**
+
+ @todo add description
+
+**/
+UINT32
+GetApicID (
+ VOID
+)
+{
+ UINT32 RegEbx;
+
+ AsmCpuid (EFI_CPUID_VERSION_INFO, NULL, &RegEbx, NULL, NULL);
+ return (UINT32)(RegEbx >> 24);
+}
+
+/**
+
+ @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,
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_STALL_PPI *PeiStall
+ )
+{
+ UINT64 ApicBaseReg;
+ EFI_PHYSICAL_ADDRESS ApicBase;
+ UINT32 ICRLow;
+ UINT32 ICRHigh;
+
+ //
+ // 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;
+ }
+
+ switch (BroadcastMode) {
+ case BROADCAST_MODE_SPECIFY_CPU:
+ 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;
+
+ *(volatile UINT32 *) (UINTN) (ApicBase + APIC_REGISTER_ICR_HIGH_OFFSET) = ICRHigh;
+ *(volatile UINT32 *) (UINTN) (ApicBase + APIC_REGISTER_ICR_LOW_OFFSET) = ICRLow;
+
+ PeiStall->Stall(
+ PeiServices,
+ PeiStall,
+ 10
+ );
+
+ ICRLow = *(volatile UINT32 *) (UINTN) (ApicBase + APIC_REGISTER_ICR_LOW_OFFSET);
+ if (ICRLow & 0x1000) {
+ return EFI_NOT_READY;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+
+ @todo Add function description
+
+ @param[in] BSP - @todo add argument description
+ @param[in] VirtualWireMode - @todo add argument description
+
+ @retval @todo add return values
+
+**/
+VOID
+ProgramVirtualWireMode (
+ BOOLEAN BSP,
+ UINT32 VirtualWireMode
+ )
+{
+ UINT64 ApicBaseReg;
+ EFI_PHYSICAL_ADDRESS ApicBase;
+ volatile UINT32 *EntryAddress;
+ UINT32 EntryValue;
+
+ ApicBaseReg = AsmReadMsr64 (EFI_MSR_IA32_APIC_BASE);
+ ApicBase = ApicBaseReg & B_EFI_MSR_IA32_APIC_BASE_APIC_BASE_ADDRESS;
+
+ //
+ // Program the Spurious Vectore entry
+ //
+ EntryAddress = (UINT32 *) (UINTN) (ApicBase + APIC_REGISTER_SPURIOUS_VECTOR_OFFSET);
+ EntryValue = *EntryAddress;
+ EntryValue &= 0xFFFFFD0F;
+ EntryValue |= 0x10F;
+ *EntryAddress = EntryValue;
+
+ //
+ // Program the LINT1 vector entry as extINT
+ //
+ EntryAddress = (UINT32 *) (UINTN) (ApicBase + APIC_REGISTER_LINT0_VECTOR_OFFSET);
+ EntryValue = *EntryAddress;
+ if (VirtualWireMode != 0) {
+ EntryValue |= 0x10000;
+ } else {
+ if (BSP) {
+ EntryValue &= 0xFFFE00FF;
+ EntryValue |= 0x700;
+ } else {
+ EntryValue |= 0x10000;
+ }
+ }
+ *EntryAddress = EntryValue;
+
+ //
+ // Program the LINT1 vector entry as NMI
+ //
+ EntryAddress = (UINT32 *) (UINTN) (ApicBase + APIC_REGISTER_LINT1_VECTOR_OFFSET);
+ EntryValue = *EntryAddress;
+ EntryValue &= 0xFFFE00FF;
+ if (BSP) {
+ EntryValue |= 0x400;
+ } else {
+ EntryValue |= 0x10400;
+ }
+ *EntryAddress = EntryValue;
+
+ if (VirtualWireMode && BSP) {
+ //
+ // Initialize the I0XApic RT table for virtual wire B
+ //
+ *(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 () << 24);
+ }
+
+}
+
+/**
+
+ @todo Add description
+
+**/
+VOID
+InitializeFeatures (
+ IN MP_CPU_S3_SCRIPT_DATA *ScriptTable
+ )
+{
+ UINT32 RegEbx;
+ UINT32 ApicId;
+ UINT8 SkipMsr;
+ //
+ // Restore all the MSRs for processor
+ //
+ AsmCpuid (EFI_CPUID_VERSION_INFO, NULL, &RegEbx, NULL, NULL);
+ ApicId = (RegEbx >> 24);
+
+ while (ScriptTable->MsrIndex != 0) {
+ if (ApicId == ScriptTable->ApicId) {
+ SkipMsr = 0;
+ if ( (ScriptTable->MsrIndex == EFI_MSR_PMG_CST_CONFIG) &&
+ (AsmReadMsr64(EFI_MSR_PMG_CST_CONFIG) & B_EFI_MSR_PMG_CST_CONFIG_CST_CONTROL_LOCK) ) {
+ SkipMsr = 1;
+ }
+ if (SkipMsr == 0) {
+ AsmWriteMsr64 (ScriptTable->MsrIndex, ScriptTable->MsrValue);
+ }
+ }
+ ScriptTable++;
+ }
+}
+
+/**
+
+ @todo Add description
+
+**/
+VOID
+MPRendezvousProcedure (
+ MP_CPU_EXCHANGE_INFO *ExchangeInfo,
+ UINT64 *MtrrValues
+ )
+{
+ UINT32 FailedRevision;
+ BOOLEAN VerifyMicrocodeChecksum;
+
+ ProgramVirtualWireMode (FALSE, ExchangeInfo->VirtualWireMode);
+ VerifyMicrocodeChecksum = ExchangeInfo->VerifyMicrocodeChecksum;
+ InitializeMicrocode ((EFI_CPU_MICROCODE_HEADER **)(UINTN)ExchangeInfo->MicrocodePointer, &FailedRevision, FALSE, &VerifyMicrocodeChecksum);
+ // TODO: InitializeFeatures (ExchangeInfo->S3BootScriptTable);
+ MpMtrrSynchUp (MtrrValues);
+
+ AsmAcquireMPLock ((UINT8 *)&(ExchangeInfo->SerializeLock));
+ ExchangeInfo->FinishedCount++;
+ AsmReleaseMPLock ((UINT8 *)&(ExchangeInfo->SerializeLock));
+}
+
+/**
+
+ Wake up all the application processors
+
+ @param[in] ImageHandle - Image handle of the loaded driver
+
+ @retval EFI_SUCCESS - APs are successfully waked up
+
+**/
+EFI_STATUS
+WakeUpAPs (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_STALL_PPI *PeiStall,
+ ACPI_CPU_DATA_COMPATIBILITY *mAcpiCpuData,
+ UINT64 *MtrrValues,
+ IN BOOLEAN VerifyMicrocodeChecksum
+ )
+{
+ EFI_PHYSICAL_ADDRESS WakeUpBuffer;
+ MP_CPU_EXCHANGE_INFO *ExchangeInfo;
+ MP_CPU_S3_DATA_POINTER *CpuS3DataPtr;
+
+ WakeUpBuffer = mAcpiCpuData->WakeUpBuffer;
+ CopyMem ((VOID *) (UINTN) WakeUpBuffer, AsmGetAddressMap(), 0x1000 - 0x200);
+
+ ExchangeInfo = (MP_CPU_EXCHANGE_INFO *) (UINTN) (WakeUpBuffer + (0x1000 - 0x200));
+
+ ExchangeInfo->Lock = 0;
+ ExchangeInfo->StackStart = (UINTN) mAcpiCpuData->StackAddress;
+ ExchangeInfo->StackSize = STACK_SIZE_PER_PROC;
+ ExchangeInfo->ApFunction = (UINT32) MPRendezvousProcedure;
+ ExchangeInfo->BufferStart = (UINT32) WakeUpBuffer;
+ ExchangeInfo->PmodeOffset = (UINT32) (AsmGetPmodeOffset ());
+ ExchangeInfo->AcpiCpuDataAddress = (UINT32) mAcpiCpuData;
+ ExchangeInfo->MtrrValuesAddress = (UINT32) MtrrValues;
+ ExchangeInfo->FinishedCount = (UINT32) 0;
+ ExchangeInfo->SerializeLock = (UINT32) 0;
+ ExchangeInfo->MicrocodePointer = (UINT32) (UINTN)mAcpiCpuData->MicrocodePointerBuffer;
+ ExchangeInfo->StartState = (UINT32) 0;
+
+ CpuS3DataPtr = (MP_CPU_S3_DATA_POINTER *)(UINTN)mAcpiCpuData->CpuPrivateData;
+ ExchangeInfo->S3BootScriptTable = (MP_CPU_S3_SCRIPT_DATA *)(UINTN)CpuS3DataPtr->S3BootScriptTable;
+ ExchangeInfo->VirtualWireMode = CpuS3DataPtr->VirtualWireMode;
+ ExchangeInfo->VerifyMicrocodeChecksum = VerifyMicrocodeChecksum;
+
+ CopyMem ((VOID *) (UINTN) &ExchangeInfo->GdtrProfile, (VOID *) (UINTN) mAcpiCpuData->GdtrProfile, sizeof (IA32_DESCRIPTOR));
+ CopyMem ((VOID *) (UINTN) &ExchangeInfo->IdtrProfile, (VOID *) (UINTN) mAcpiCpuData->IdtrProfile, sizeof (IA32_DESCRIPTOR));
+
+ DEBUG ((DEBUG_ERROR, "Cpu S3 Bootscript at %08X\n", (UINT32)ExchangeInfo->S3BootScriptTable));
+
+ //
+ // Don't touch MPCPU private data
+ // Here we use ExchangeInfo instead
+ //
+
+ //
+ // Send INIT IPI - SIPI to all APs
+ //
+ SendInterrupt (
+ BROADCAST_MODE_ALL_EXCLUDING_SELF,
+ 0,
+ 0,
+ DELIVERY_MODE_INIT,
+ TRIGGER_MODE_EDGE,
+ TRUE,
+ PeiServices,
+ PeiStall
+ );
+
+ SendInterrupt (
+ BROADCAST_MODE_ALL_EXCLUDING_SELF,
+ 0,
+ (UINT32) RShiftU64 (WakeUpBuffer, 12),
+ DELIVERY_MODE_SIPI,
+ TRIGGER_MODE_EDGE,
+ TRUE,
+ PeiServices,
+ PeiStall
+ );
+ while (ExchangeInfo->FinishedCount < mAcpiCpuData->NumberOfCpus - 1) {
+ CpuPause ();
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+
+ This routine is used to search SMRAM and get SmramCpuData point.
+
+ @param[in] PeiServices - PEI services global pointer
+ @param[in] SmmAccessPpi - SmmAccess PPI instance
+
+@returns SmramCpuData - The pointer of CPU information in SMRAM.
+
+**/
+STATIC
+SMRAM_CPU_DATA *
+GetSmmCpuData (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_SMM_ACCESS_PPI *SmmAccessPpi
+ )
+{
+ EFI_SMRAM_DESCRIPTOR *SmramRanges;
+ UINTN SmramRangeCount;
+ UINTN Size;
+ EFI_STATUS Status;
+ UINT32 Address;
+ SMRAM_CPU_DATA *SmramCpuData;
+
+ //
+ // Get all SMRAM range
+ //
+ Size = 0;
+ Status = SmmAccessPpi->GetCapabilities (PeiServices, SmmAccessPpi, &Size, NULL);
+ ASSERT (Status == EFI_BUFFER_TOO_SMALL);
+
+ Status = PeiServicesAllocatePool (
+ Size,
+ (VOID **)&SmramRanges
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = SmmAccessPpi->GetCapabilities (PeiServices, SmmAccessPpi, &Size, SmramRanges);
+ ASSERT_EFI_ERROR (Status);
+
+ Size /= sizeof (*SmramRanges);
+ SmramRangeCount = Size;
+
+ //
+ // BUGBUG: We assume TSEG is the last range of SMRAM in SmramRanges
+ //
+ SmramRanges += SmramRangeCount - 1;
+
+ DEBUG (( DEBUG_ERROR, "TsegBase - %x\n", SmramRanges->CpuStart));
+ DEBUG (( DEBUG_ERROR, "TsegTop - %x\n", SmramRanges->CpuStart + SmramRanges->PhysicalSize));
+
+ //
+ // Search SMRAM on page alignment for the SMMNVS signature
+ //
+ for (Address = (UINT32)(SmramRanges->CpuStart + SmramRanges->PhysicalSize - EFI_PAGE_SIZE);
+ Address >= (UINT32)SmramRanges->CpuStart;
+ Address -= EFI_PAGE_SIZE) {
+ SmramCpuData = (SMRAM_CPU_DATA *)(UINTN)Address;
+ if (CompareGuid (&SmramCpuData->HeaderGuid, &mSmramCpuNvsHeaderGuid)) {
+ //
+ // Find it
+ //
+ return SmramCpuData;
+ }
+ }
+
+ ASSERT (FALSE);
+
+ return NULL;
+}
+
+/**
+
+ This routine is restore the CPU information from SMRAM to original reserved memory region.
+
+ @param[in] PeiServices - PEI services global pointer
+
+ @returns AcpiCpuData - The pointer of CPU information in reserved memory.
+
+**/
+ACPI_CPU_DATA_COMPATIBILITY *
+RestoreSmramCpuData (
+ IN CONST EFI_PEI_SERVICES **PeiServices
+ )
+{
+ PEI_SMM_ACCESS_PPI *SmmAccessPpi;
+ SMRAM_CPU_DATA *SmramCpuData;
+ EFI_STATUS Status;
+ ACPI_CPU_DATA_COMPATIBILITY *AcpiCpuData;
+ MP_CPU_S3_DATA_POINTER *CpuS3DataPtr;
+ IA32_DESCRIPTOR *Idtr;
+ IA32_DESCRIPTOR *Gdtr;
+ UINTN MicrocodeSize;
+ EFI_CPU_MICROCODE_HEADER **Microcode;
+ EFI_CPU_MICROCODE_HEADER *LockBoxMicrocode;
+ UINTN Index;
+
+ Status = PeiServicesLocatePpi (
+ &gPeiSmmAccessPpiGuid,
+ 0,
+ NULL,
+ (VOID **)&SmmAccessPpi
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Open all SMM regions
+ //
+ Index = 0;
+ do {
+ Status = SmmAccessPpi->Open ((EFI_PEI_SERVICES**)PeiServices, SmmAccessPpi, Index);
+ Index++;
+ } while (!EFI_ERROR (Status));
+
+ SmramCpuData = GetSmmCpuData ((EFI_PEI_SERVICES**)PeiServices, SmmAccessPpi);
+ if (SmramCpuData == NULL) {
+ ASSERT(SmramCpuData != NULL);
+ return NULL;
+ }
+
+ DEBUG ((DEBUG_ERROR, "CpuS3 SmramCpuData - 0x%x \n", SmramCpuData));
+
+ DEBUG ((DEBUG_ERROR, "SmramCpuData->GdtrProfileSize - %x\n", SmramCpuData->GdtrProfileSize));
+ DEBUG ((DEBUG_ERROR, "SmramCpuData->GdtSize - %x\n", SmramCpuData->GdtSize));
+ DEBUG ((DEBUG_ERROR, "SmramCpuData->IdtrProfileSize - %x\n", SmramCpuData->IdtrProfileSize));
+ DEBUG ((DEBUG_ERROR, "SmramCpuData->IdtSize - %x\n", SmramCpuData->IdtSize));
+ DEBUG ((DEBUG_ERROR, "SmramCpuData->CpuPrivateDataSize - %x\n", SmramCpuData->CpuPrivateDataSize));
+ DEBUG ((DEBUG_ERROR, "SmramCpuData->S3BootScriptTableSize - %x\n", SmramCpuData->S3BootScriptTableSize));
+ DEBUG ((DEBUG_ERROR, "SmramCpuData->S3BspMtrrTableSize - %x\n", SmramCpuData->S3BspMtrrTableSize));
+ DEBUG ((DEBUG_ERROR, "SmramCpuData->MicrocodePointerBufferSize - %x\n", SmramCpuData->MicrocodePointerBufferSize));
+ DEBUG ((DEBUG_ERROR, "SmramCpuData->MicrocodeDataBufferSize - %x\n", SmramCpuData->MicrocodeDataBufferSize));
+
+ DEBUG ((DEBUG_ERROR, "SmramCpuData->GdtrProfileOffset - %x\n", SmramCpuData->GdtrProfileOffset));
+ DEBUG ((DEBUG_ERROR, "SmramCpuData->GdtOffset - %x\n", SmramCpuData->GdtOffset));
+ DEBUG ((DEBUG_ERROR, "SmramCpuData->IdtrProfileOffset - %x\n", SmramCpuData->IdtrProfileOffset));
+ DEBUG ((DEBUG_ERROR, "SmramCpuData->IdtOffset - %x\n", SmramCpuData->IdtOffset));
+ DEBUG ((DEBUG_ERROR, "SmramCpuData->CpuPrivateDataOffset - %x\n", SmramCpuData->CpuPrivateDataOffset));
+ DEBUG ((DEBUG_ERROR, "SmramCpuData->S3BootScriptTableOffset - %x\n", SmramCpuData->S3BootScriptTableOffset));
+ DEBUG ((DEBUG_ERROR, "SmramCpuData->S3BspMtrrTableOffset - %x\n", SmramCpuData->S3BspMtrrTableOffset));
+ DEBUG ((DEBUG_ERROR, "SmramCpuData->MicrocodePointerBufferOffset - %x\n", SmramCpuData->MicrocodePointerBufferOffset));
+ DEBUG ((DEBUG_ERROR, "SmramCpuData->MicrocodeDataBufferOffset - %x\n", SmramCpuData->MicrocodeDataBufferOffset));
+
+ //
+ // Start restore data to NVS
+ //
+ AcpiCpuData = (ACPI_CPU_DATA_COMPATIBILITY *)(UINTN)SmramCpuData->AcpiCpuPointer;
+ CopyMem (AcpiCpuData, &SmramCpuData->AcpiCpuData, sizeof (ACPI_CPU_DATA_COMPATIBILITY));
+
+ DEBUG ((DEBUG_ERROR, "AcpiCpuData->WakeUpBuffer - %x\n", AcpiCpuData->WakeUpBuffer));
+ DEBUG ((DEBUG_ERROR, "AcpiCpuData->GdtrProfile - %x\n", AcpiCpuData->GdtrProfile));
+ DEBUG ((DEBUG_ERROR, "AcpiCpuData->IdtrProfile - %x\n", AcpiCpuData->IdtrProfile));
+ DEBUG ((DEBUG_ERROR, "AcpiCpuData->CpuPrivateData - %x\n", AcpiCpuData->CpuPrivateData));
+ DEBUG ((DEBUG_ERROR, "AcpiCpuData->StackAddress - %x\n", AcpiCpuData->StackAddress));
+ DEBUG ((DEBUG_ERROR, "AcpiCpuData->MicrocodePointerBuffer - %x\n", AcpiCpuData->MicrocodePointerBuffer));
+ DEBUG ((DEBUG_ERROR, "AcpiCpuData->SmramBase - %x\n", AcpiCpuData->SmramBase));
+ DEBUG ((DEBUG_ERROR, "AcpiCpuData->SmmStartImageBase - %x\n", AcpiCpuData->SmmStartImageBase));
+
+ CopyMem (
+ (VOID *)(UINTN)AcpiCpuData->GdtrProfile,
+ (UINT8 *)SmramCpuData + SmramCpuData->GdtrProfileOffset,
+ SmramCpuData->GdtrProfileSize
+ );
+ Gdtr = (IA32_DESCRIPTOR *)(UINTN)AcpiCpuData->GdtrProfile;
+ CopyMem (
+ (VOID *)(UINTN)Gdtr->Base,
+ (UINT8 *)SmramCpuData + SmramCpuData->GdtOffset,
+ SmramCpuData->GdtSize
+ );
+ DEBUG ((DEBUG_ERROR, "Gdtr->Base - %x\n", (UINT32) (Gdtr->Base)));
+ CopyMem (
+ (VOID *)(UINTN)AcpiCpuData->IdtrProfile,
+ (UINT8 *)SmramCpuData + SmramCpuData->IdtrProfileOffset,
+ SmramCpuData->IdtrProfileSize
+ );
+ Idtr = (IA32_DESCRIPTOR *)(UINTN)AcpiCpuData->IdtrProfile;
+ CopyMem (
+ (VOID *)(UINTN)Idtr->Base,
+ (UINT8 *)SmramCpuData + SmramCpuData->IdtOffset,
+ SmramCpuData->IdtSize
+ );
+ DEBUG ((DEBUG_ERROR, "Idtr->Base - %x\n", (UINT32) (Idtr->Base)));
+ CopyMem (
+ (VOID *)(UINTN)AcpiCpuData->CpuPrivateData,
+ (UINT8 *)SmramCpuData + SmramCpuData->CpuPrivateDataOffset,
+ SmramCpuData->CpuPrivateDataSize
+ );
+ CpuS3DataPtr = (MP_CPU_S3_DATA_POINTER *)(UINTN)AcpiCpuData->CpuPrivateData;
+
+ //
+ // TODO:
+ // CopyMem (
+ // (VOID *)(UINTN)CpuS3DataPtr->S3BootScriptTable,
+ // (UINT8 *)SmramCpuData + SmramCpuData->S3BootScriptTableOffset,
+ // SmramCpuData->S3BootScriptTableSize
+ // );
+ //
+ DEBUG ((DEBUG_ERROR, "CpuS3DataPtr->S3BootScriptTable - %x\n", (UINT32) (CpuS3DataPtr->S3BootScriptTable)));
+
+ //
+ // TODO: BSP MTRRs are initialized by FSP.
+ // CopyMem (
+ // (VOID *)(UINTN)CpuS3DataPtr->S3BspMtrrTable,
+ // (UINT8 *)SmramCpuData + SmramCpuData->S3BspMtrrTableOffset,
+ // SmramCpuData->S3BspMtrrTableSize
+ // );
+ DEBUG ((DEBUG_ERROR, "CpuS3DataPtr->S3BspMtrrTable - %x\n", (UINT32) (CpuS3DataPtr->S3BspMtrrTable)));
+ CopyMem (
+ (VOID *)(UINTN)AcpiCpuData->MicrocodePointerBuffer,
+ (UINT8 *)SmramCpuData + SmramCpuData->MicrocodePointerBufferOffset,
+ SmramCpuData->MicrocodePointerBufferSize
+ );
+
+ //
+ // Restore Microcode Data
+ //
+ Microcode = (VOID *)(UINTN)AcpiCpuData->MicrocodePointerBuffer;
+ LockBoxMicrocode = (EFI_CPU_MICROCODE_HEADER *)((UINT8 *)SmramCpuData + SmramCpuData->MicrocodeDataBufferOffset);
+ if (Microcode != NULL) {
+ Index = 0;
+ MicrocodeSize = 0;
+ while (Microcode[Index] != NULL) {
+ if (LockBoxMicrocode->DataSize == 0) {
+ MicrocodeSize = 2048;
+ } else {
+ MicrocodeSize = LockBoxMicrocode->TotalSize;
+ }
+ CopyMem (Microcode[Index], LockBoxMicrocode, MicrocodeSize);
+ LockBoxMicrocode = (EFI_CPU_MICROCODE_HEADER *)((UINT8 *)LockBoxMicrocode + MicrocodeSize);
+ Index ++;
+ }
+ }
+
+ //
+ // Close all SMM regions
+ //
+ Index = 0;
+ do {
+ Status = SmmAccessPpi->Close ((EFI_PEI_SERVICES**)PeiServices, SmmAccessPpi, Index);
+ Index++;
+ } while (!EFI_ERROR (Status));
+
+ return AcpiCpuData;
+}
+
+/**
+
+ Initialize multiple processors.
+
+ @param[in] ImageHandle - Image handle of the loaded driver
+ @param[in] SystemTable - Pointer to the System Table
+
+ @retval EFI_SUCCESS - Multiple processors are intialized successfully
+
+**/
+EFI_STATUS
+InitializeCpu (
+ IN EFI_PEI_FILE_HANDLE FileHandle,
+ IN CONST EFI_PEI_SERVICES **PeiServices
+ )
+{
+ EFI_STATUS Status;
+ EFI_PEI_STALL_PPI *PeiStall;
+ ACPI_CPU_DATA_COMPATIBILITY *mAcpiCpuData;
+ EFI_BOOT_MODE BootMode;
+ UINT32 FailedRevision;
+ UINT64 *MtrrValues;
+ MP_CPU_S3_DATA_POINTER *CpuS3DataPtr;
+ BOOLEAN VerifyMicrocodeChecksum;
+
+ DEBUG ((DEBUG_ERROR, "Cpu S3 dispatch\n"));
+
+ Status = (*PeiServices)->GetBootMode (PeiServices, &BootMode);
+ if (EFI_ERROR (Status)) {
+ //
+ // If not in S3 boot path. do nothing
+ //
+ return EFI_SUCCESS;
+ }
+
+ if (BootMode != BOOT_ON_S3_RESUME) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Restore ACPI Nvs data from SMRAM
+ //
+
+ mAcpiCpuData = RestoreSmramCpuData (PeiServices);
+
+ DEBUG ((DEBUG_ERROR, "CpuS3 RestoreSmramCpuData - 0x%x \n", mAcpiCpuData));
+ if (mAcpiCpuData == NULL) {
+ ASSERT(mAcpiCpuData != NULL);
+ return EFI_NOT_READY;
+ }
+
+ mAcpiCpuData->S3BootPath = TRUE;
+
+ Status = PeiServicesLocatePpi (
+ &gEfiPeiStallPpiGuid,
+ 0,
+ NULL,
+ (VOID **)&PeiStall
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ CpuS3DataPtr = (MP_CPU_S3_DATA_POINTER *)(UINTN)mAcpiCpuData->CpuPrivateData;
+
+ //
+ // Program virtual wire mode for BSP
+ //
+ ProgramVirtualWireMode (TRUE, CpuS3DataPtr->VirtualWireMode);
+ VerifyMicrocodeChecksum = TRUE;
+ InitializeMicrocode ((EFI_CPU_MICROCODE_HEADER **)(UINTN) mAcpiCpuData->MicrocodePointerBuffer, &FailedRevision, TRUE, &VerifyMicrocodeChecksum);
+
+ //
+ // Restore features for BSP
+ //
+ // TODO: InitializeFeatures ((MP_CPU_S3_SCRIPT_DATA *)CpuS3DataPtr->S3BootScriptTable);
+
+ Status = PeiServicesAllocatePool (
+ (FixedMtrrNumber + MtrrDefTypeNumber + VariableMtrrNumber) * sizeof (UINT64),
+ (VOID **) &MtrrValues
+ );
+ //
+ // TODO: This has been done by FSP.
+ // SetBspMtrrRegisters ((EFI_MTRR_VALUES *)CpuS3DataPtr->S3BspMtrrTable);
+ //
+ ReadMtrrRegisters (MtrrValues);
+
+ //
+ // Restore configuration for APs and synch up Ap's MTRRs with BSP
+ //
+ WakeUpAPs ((CONST EFI_PEI_SERVICES**)PeiServices, PeiStall, mAcpiCpuData, MtrrValues, VerifyMicrocodeChecksum);
+
+ return EFI_SUCCESS;
+}
+
diff --git a/ChvRefCodePkg/CherryViewSoc/CPU/CpuS3/MpS3.inf b/ChvRefCodePkg/CherryViewSoc/CPU/CpuS3/MpS3.inf
new file mode 100644
index 0000000000..d8f6e2c094
--- /dev/null
+++ b/ChvRefCodePkg/CherryViewSoc/CPU/CpuS3/MpS3.inf
@@ -0,0 +1,50 @@
+## @file
+# Component description file for CPU S3 module.
+#
+# 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 = MpS3
+ FILE_GUID = C866BD71-7C79-4BF1-A93B-066B830D8F9A
+ MODULE_TYPE = PEIM
+ VERSION_STRING = 1.0
+ ENTRY_POINT = InitializeCpu
+
+[sources]
+ MpS3.c
+ MtrrSync.c
+ Microcode.c
+ HtFuncs.asm | MSFT
+ HtFuncs.s | GCC
+ CpuAsm.asm | MSFT
+ CpuAsm.s | GCC
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ ChvRefCodePkg/ChvRefCodePkg.dec
+
+[LibraryClasses]
+ BaseMemoryLib
+ PeimEntryPoint
+ DebugLib
+ PeiServicesLib
+
+[Ppis]
+ gEfiPeiStallPpiGuid # CONSUMES
+ gPeiSmmAccessPpiGuid # CONSUMES
+
+[Depex]
+ gEfiPeiMasterBootModePpiGuid AND gEfiPeiMemoryDiscoveredPpiGuid AND gPeiSmmAccessPpiGuid
+
diff --git a/ChvRefCodePkg/CherryViewSoc/CPU/CpuS3/MtrrSync.c b/ChvRefCodePkg/CherryViewSoc/CPU/CpuS3/MtrrSync.c
new file mode 100644
index 0000000000..70aaa36ee2
--- /dev/null
+++ b/ChvRefCodePkg/CherryViewSoc/CPU/CpuS3/MtrrSync.c
@@ -0,0 +1,239 @@
+/** @file
+ Synchronization of MTRRs on S3 boot path.
+
+ 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"
+
+UINTN
+MpMtrrSynchUpEntry (
+ VOID
+ )
+;
+
+VOID
+MpMtrrSynchUpExit (
+ UINTN Cr4
+ )
+;
+
+UINT16 mFixedMtrrIndex[] = {
+ EFI_MSR_IA32_MTRR_FIX64K_00000,
+ EFI_MSR_IA32_MTRR_FIX16K_80000,
+ EFI_MSR_IA32_MTRR_FIX16K_A0000,
+ EFI_MSR_IA32_MTRR_FIX4K_C0000,
+ EFI_MSR_IA32_MTRR_FIX4K_C8000,
+ EFI_MSR_IA32_MTRR_FIX4K_D0000,
+ EFI_MSR_IA32_MTRR_FIX4K_D8000,
+ EFI_MSR_IA32_MTRR_FIX4K_E0000,
+ EFI_MSR_IA32_MTRR_FIX4K_E8000,
+ EFI_MSR_IA32_MTRR_FIX4K_F0000,
+ EFI_MSR_IA32_MTRR_FIX4K_F8000,
+};
+
+UINT16 mMtrrDefType[] = {EFI_MSR_CACHE_IA32_MTRR_DEF_TYPE};
+
+UINT16 mVariableMtrrIndex[] = {
+ EFI_MSR_CACHE_VARIABLE_MTRR_BASE,
+ EFI_MSR_CACHE_VARIABLE_MTRR_BASE + 1,
+ EFI_MSR_CACHE_VARIABLE_MTRR_BASE + 2,
+ EFI_MSR_CACHE_VARIABLE_MTRR_BASE + 3,
+ EFI_MSR_CACHE_VARIABLE_MTRR_BASE + 4,
+ EFI_MSR_CACHE_VARIABLE_MTRR_BASE + 5,
+ EFI_MSR_CACHE_VARIABLE_MTRR_BASE + 6,
+ EFI_MSR_CACHE_VARIABLE_MTRR_BASE + 7,
+ EFI_MSR_CACHE_VARIABLE_MTRR_BASE + 8,
+ EFI_MSR_CACHE_VARIABLE_MTRR_BASE + 9,
+ EFI_MSR_CACHE_VARIABLE_MTRR_BASE + 10,
+ EFI_MSR_CACHE_VARIABLE_MTRR_BASE + 11,
+ EFI_MSR_CACHE_VARIABLE_MTRR_BASE + 12,
+ EFI_MSR_CACHE_VARIABLE_MTRR_BASE + 13,
+ EFI_MSR_CACHE_VARIABLE_MTRR_BASE + 14,
+ EFI_MSR_CACHE_VARIABLE_MTRR_END,
+};
+
+UINTN FixedMtrrNumber = sizeof (mFixedMtrrIndex) / sizeof (UINT16);
+UINTN MtrrDefTypeNumber = sizeof (mMtrrDefType) / sizeof (UINT16);
+UINTN VariableMtrrNumber = sizeof (mVariableMtrrIndex) / sizeof (UINT16);
+
+/**
+
+ @todo Add function description
+
+ @retval EFI_SUCCESS - @todo Add description for return value
+
+**/
+VOID
+DisableCacheAsRam (
+ )
+{
+ UINT64 CacheAsRamMsr;
+
+ CacheAsRamMsr = AsmReadMsr64 (0x000002E0);
+
+ //
+ // Per Pineview BWG section 3.21, BIOS must set the Disable FERR Assertion
+ //
+// CacheAsRamMsr |= B_EFI_MSR_NO_EVICT_MODE_DISABLE_FERR;
+// AsmWriteMsr64 (0x000002E0, CacheAsRamMsr);
+
+ //
+ // Step 3: Disable No-Eviction Mode Run State by clearing
+ // NO_EVICT_MODE MSR 2E0h bit [1] = 0
+ CacheAsRamMsr &= (~(UINT64)BIT1);
+ AsmWriteMsr64 (0x000002E0, CacheAsRamMsr);
+
+ // Step 4: Disable No-Eviction Mode Setup State by clearing
+ // NO_EVICT_MODE MSR 2E0h bit [0] = 0
+ CacheAsRamMsr &= (~(UINT64)BIT0);
+ AsmWriteMsr64 (0x000002E0, CacheAsRamMsr);
+}
+
+/**
+
+ Save the MTRR registers to global variables
+
+**/
+VOID
+ReadMtrrRegisters (
+ UINT64 *MtrrValues
+ )
+{
+ UINT32 Index, IndexEnd;
+ //
+ // Read all Mtrrs
+ //
+ for (Index = 0; Index < FixedMtrrNumber; Index++) {
+ *MtrrValues = AsmReadMsr64 (mFixedMtrrIndex[Index]);
+ MtrrValues++;
+ }
+
+ for (Index = 0; Index < MtrrDefTypeNumber; Index++) {
+ *MtrrValues = AsmReadMsr64 (mMtrrDefType[Index]);
+ MtrrValues++;
+ }
+
+ 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 (mVariableMtrrIndex) / sizeof (UINT16))) {
+ *MtrrValues = AsmReadMsr64 (mVariableMtrrIndex[Index]);
+ MtrrValues++;
+ }
+ }
+}
+
+/**
+
+ Synch up the MTRR values for all processors
+
+**/
+// @todo Buffer - add argument and description to function comment
+VOID
+MpMtrrSynchUp (
+ UINT64 *MtrrValues
+ )
+{
+ UINT32 Index, IndexEnd;
+ UINTN Cr4;
+ UINT64 *FixedMtrr;
+ UINT64 *MtrrDefType;
+ UINT64 *VariableMtrr;
+ UINT64 ValidMtrrAddressMask;
+ UINT8 PhysicalAddressBits;
+ UINT32 RegEax;
+
+ //
+ // Get physical CPU MTRR width in case of difference from BSP
+ //
+ AsmCpuid (EFI_CPUID_EXTENDED_FUNCTION, &RegEax, NULL, NULL, NULL);
+ PhysicalAddressBits = 36;
+ if (RegEax >= EFI_CPUID_VIRT_PHYS_ADDRESS_SIZE) {
+ AsmCpuid (EFI_CPUID_VIRT_PHYS_ADDRESS_SIZE, &RegEax, NULL, NULL, NULL);
+ PhysicalAddressBits = (UINT8) RegEax;
+ }
+
+ ValidMtrrAddressMask = (LShiftU64(1, PhysicalAddressBits) - 1) & 0xfffffffffffff000;
+
+ FixedMtrr = MtrrValues;
+ MtrrDefType = MtrrValues + FixedMtrrNumber;
+ VariableMtrr = MtrrValues + FixedMtrrNumber + MtrrDefTypeNumber;
+
+ //
+ // ASM code to setup processor register before synching up the MTRRs
+ //
+ Cr4 = MpMtrrSynchUpEntry ();
+
+ //
+ // Make sure all threads has FERR disabled per Pineview BWG section 3.21
+ //
+ //DisableCacheAsRam ();
+
+ //
+ // Disable Fixed Mtrrs
+ //
+ AsmWriteMsr64 (EFI_MSR_CACHE_IA32_MTRR_DEF_TYPE, MtrrDefType[0] & 0xFFFFF7FF);
+
+ //
+ // Update Fixed Mtrrs
+ //
+ for (Index = 0; Index < FixedMtrrNumber; Index++) {
+ AsmWriteMsr64 (mFixedMtrrIndex[Index], FixedMtrr[Index]);
+ }
+
+ //
+ // 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 ++) {
+ if ((Index < (sizeof (mVariableMtrrIndex) / sizeof (UINT16))) && (Index < VariableMtrrNumber ) ) {
+ AsmWriteMsr64 (mVariableMtrrIndex[Index], (VariableMtrr[Index] & 0x0FFF) | (VariableMtrr[Index] & ValidMtrrAddressMask));
+ }
+ }
+
+ //
+ // Synchup def type Fixed Mtrrs
+ //
+ AsmWriteMsr64 (EFI_MSR_CACHE_IA32_MTRR_DEF_TYPE, MtrrDefType[0]);
+
+ //
+ // ASM code to setup processor register after synching up the MTRRs
+ //
+ MpMtrrSynchUpExit (Cr4);
+
+ return ;
+}
+
+VOID
+SetBspMtrrRegisters (
+ IN EFI_MTRR_VALUES *MtrrArray
+ )
+{
+ UINT32 Index;
+ UINTN Cr4;
+
+ //
+ // ASM code to setup processor register before synching up the MTRRs
+ //
+ Cr4 = MpMtrrSynchUpEntry ();
+
+ Index = 0;
+ while (MtrrArray[Index].Index != 0) {
+ AsmWriteMsr64 (MtrrArray[Index].Index, MtrrArray[Index].Value);
+ Index++;
+ }
+
+ //
+ // ASM code to setup processor register after synching up the MTRRs
+ //
+ MpMtrrSynchUpExit (Cr4);
+}