1 ;------------------------------------------------------------------------------ ;
2 ; Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>
3 ; This program and the accompanying materials
4 ; are licensed and made available under the terms and conditions of the BSD License
5 ; which accompanies this distribution. The full text of the license may be found at
6 ; http://opensource.org/licenses/bsd-license.php.
8 ; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
9 ; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 ; This is the assembly code for MP support
19 ;-------------------------------------------------------------------------------
22 extern InitializeFloatingPointUnits:PROC
25 ;-------------------------------------------------------------------------------------
26 ;RendezvousFunnelProc procedure follows. All APs execute their procedure. This
27 ;procedure serializes all the AP processors through an Init sequence. It must be
28 ;noted that APs arrive here very raw...ie: real mode, no stack.
29 ;ALSO THIS PROCEDURE IS EXECUTED BY APs ONLY ON 16 BIT MODE. HENCE THIS PROC
31 ;-------------------------------------------------------------------------------------
32 RendezvousFunnelProc PROC PUBLIC
33 RendezvousFunnelProcStart::
34 ; At this point CS = 0x(vv00) and ip= 0x0.
35 ; Save BIST information to ebp firstly
36 db 66h, 08bh, 0e8h ; mov ebp, eax ; save BIST information
38 db 8ch,0c8h ; mov ax, cs
39 db 8eh,0d8h ; mov ds, ax
40 db 8eh,0c0h ; mov es, ax
41 db 8eh,0d0h ; mov ss, ax
42 db 33h,0c0h ; xor ax, ax
43 db 8eh,0e0h ; mov fs, ax
44 db 8eh,0e8h ; mov gs, ax
46 db 0BEh ; opcode of mov si, mem16
47 dw BufferStartLocation ; mov si, BufferStartLocation
48 db 66h, 8Bh, 1Ch ; mov ebx, dword ptr [si]
50 db 0BFh ; opcode of mov di, mem16
51 dw ModeOffsetLocation ; mov di, ModeOffsetLocation
52 db 66h, 8Bh, 05h ; mov eax, [di]
53 db 0BFh ; opcode of mov di, mem16
54 dw CodeSegmentLocation ; mov di, CodeSegmentLocation
55 db 66h, 8Bh, 15h ; mov edx, [di]
56 db 89h, 0C7h ; mov di, ax
57 db 83h, 0EFh, 02h ; sub di, 02h
58 db 89h, 15h ; mov [di], dx ; Patch long mode CS
59 db 83h, 0EFh, 04h ; sub di, 04h
60 db 66h, 01h, 0D8h ; add eax, ebx
61 db 66h, 89h, 05h ; mov [di], eax ; Patch address
63 db 0BEh ; opcode of mov si, mem16
64 dw GdtrLocation ; mov si, GdtrLocation
66 db 2Eh, 0Fh, 01h, 14h ; lgdt fword ptr cs:[si]
69 dw IdtrLocation ; mov si, IdtrLocation
71 db 2Eh,0Fh, 01h, 1Ch ; lidt fword ptr cs:[si]
73 db 0BFh ; opcode of mov di, mem16
74 dw DataSegmentLocation ; mov di, DataSegmentLocation
75 db 66h, 8Bh, 3Dh ; mov edi, [di] ; Save long mode DS in edi
78 dw Cr3Location ; mov si, Cr3Location
79 db 66h, 8Bh, 0Ch ; mov ecx, dword ptr [si] ; ECX is keeping the value of CR3
81 db 31h, 0C0h ; xor ax, ax
82 db 8Eh, 0D8h ; mov ds, ax ; Clear data segment
84 db 0Fh, 20h, 0C0h ; mov eax, cr0 ; Get control register 0
85 db 66h, 83h, 0C8h, 03h ; or eax, 000000003h ; Set PE bit (bit #0) & MP
86 db 0Fh, 22h, 0C0h ; mov cr0, eax
88 db 0Fh, 20h, 0E0h ; mov eax, cr4
89 db 66h, 0Fh, 0BAh, 0E8h, 05h ; bts eax, 5
90 db 0Fh, 22h, 0E0h ; mov cr4, eax
92 db 0Fh, 22h, 0D9h ; mov cr3, ecx
95 dd 0C0000080h ; mov ecx, 0c0000080h ; EFER MSR number.
96 db 0Fh, 32h ; rdmsr ; Read EFER.
97 db 66h, 0Fh, 0BAh, 0E8h, 08h; bts eax, 8 ; Set LME=1.
98 db 0Fh, 30h ; wrmsr ; Write EFER.
100 db 0Fh, 20h, 0C0h ; mov eax, cr0 ; Read CR0.
101 db 66h, 0Fh, 0BAh, 0E8h, 1Fh; bts eax, 31 ; Set PG=1.
102 db 0Fh, 22h, 0C0h ; mov cr0, eax ; Write CR0.
105 db 66h, 0EAh ; far jump
106 dd 0h ; 32-bit offset
107 dw 0h ; 16-bit selector
117 add edi, LockLocation
118 mov rax, NotVacantFlag
121 xchg qword ptr [edi], rax
122 cmp rax, NotVacantFlag
126 add edi, NumApsExecutingLoction
128 mov ebx, dword ptr [edi]
132 add edi, StackSizeLocation
133 mov rax, qword ptr [edi]
135 add edi, StackStartAddressLocation
136 add rax, qword ptr [edi]
138 mov qword ptr [edi], rax
143 add edi, LockLocation
144 xchg qword ptr [edi], rax
147 push rbp ; push BIST data
148 xor rbp, rbp ; clear ebp for call stack trace
152 mov rax, InitializeFloatingPointUnits
154 call rax ; Call assembly function to initialize FPU per UEFI spec
157 mov edx, ebx ; edx is NumApsExecuting
159 add ecx, LockLocation ; rcx is address of exchange info data buffer
162 add edi, ApProcedureLocation
163 mov rax, qword ptr [edi]
166 call rax ; invoke C function
170 RendezvousFunnelProc ENDP
171 RendezvousFunnelProcEnd::
173 ;-------------------------------------------------------------------------------------
174 ; AsmGetAddressMap (&AddressMap);
175 ;-------------------------------------------------------------------------------------
176 AsmGetAddressMap PROC
177 mov rax, offset RendezvousFunnelProcStart
178 mov qword ptr [rcx], rax
179 mov qword ptr [rcx + 8h], LongModeStart - RendezvousFunnelProcStart
180 mov qword ptr [rcx + 10h], RendezvousFunnelProcEnd - RendezvousFunnelProcStart
182 AsmGetAddressMap ENDP
184 ;-------------------------------------------------------------------------------------
185 ;AsmExchangeRole procedure follows. This procedure executed by current BSP, that is
186 ;about to become an AP. It switches it'stack with the current AP.
187 ;AsmExchangeRole (IN CPU_EXCHANGE_INFO *MyInfo, IN CPU_EXCHANGE_INFO *OthersInfo);
188 ;-------------------------------------------------------------------------------------
190 ; DO NOT call other functions in this function, since 2 CPU may use 1 stack
191 ; at the same time. If 1 CPU try to call a function, stack will be corrupted.
215 ; rsi contains MyInfo pointer
218 ; rdi contains OthersInfo pointer
221 ;Store EFLAGS, GDTR and IDTR regiter to stack
223 sgdt fword ptr [rsi + 16]
224 sidt fword ptr [rsi + 26]
226 ; Store the its StackPointer
227 mov qword ptr [rsi + 8], rsp
229 ; update its switch state to STORED
230 mov byte ptr [rsi], CPU_SWITCH_STATE_STORED
233 ; wait until the other CPU finish storing its state
234 cmp byte ptr [rdi], CPU_SWITCH_STATE_STORED
237 jmp WaitForOtherStored
240 ; Since another CPU already stored its state, load them
242 lgdt fword ptr [rdi + 16]
245 lidt fword ptr [rdi + 26]
247 ; load its future StackPointer
248 mov rsp, qword ptr [rdi + 8]
250 ; update the other CPU's switch state to LOADED
251 mov byte ptr [rdi], CPU_SWITCH_STATE_LOADED
254 ; wait until the other CPU finish loading new state,
255 ; otherwise the data in stack may corrupt
256 cmp byte ptr [rsi], CPU_SWITCH_STATE_LOADED
259 jmp WaitForOtherLoaded
262 ; since the other CPU already get the data it want, leave this procedure