1 ;------------------------------------------------------------------------------ ;
2 ; Copyright (c) 2015 - 2019, Intel Corporation. All rights reserved.<BR>
3 ; SPDX-License-Identifier: BSD-2-Clause-Patent
11 ; This is the assembly code for MP support
13 ;-------------------------------------------------------------------------------
16 extern ASM_PFX(InitializeFloatingPointUnits)
20 ;-------------------------------------------------------------------------------------
21 ;RendezvousFunnelProc procedure follows. All APs execute their procedure. This
22 ;procedure serializes all the AP processors through an Init sequence. It must be
23 ;noted that APs arrive here very raw...ie: real mode, no stack.
24 ;ALSO THIS PROCEDURE IS EXECUTED BY APs ONLY ON 16 BIT MODE. HENCE THIS PROC
26 ;-------------------------------------------------------------------------------------
27 global ASM_PFX(RendezvousFunnelProc)
28 ASM_PFX(RendezvousFunnelProc):
29 RendezvousFunnelProcStart:
30 ; At this point CS = 0x(vv00) and ip= 0x0.
32 mov ebp, eax ; save BIST information
42 mov si, BufferStartLocation
45 mov si, DataSegmentLocation
49 ; Get start address of 32-bit code in low memory (<1MB)
51 mov edi, ModeTransitionMemoryLocation
60 ; Switch to protected mode
62 mov eax, cr0 ; Get control register 0
63 or eax, 000000003h ; Set PE bit (bit #0) & MP
66 ; Switch to 32-bit code in executable memory (>1MB)
70 ; Following code may be copied to memory with type of EfiBootServicesCode.
71 ; This is required at DXE phase if NX is enabled for EfiBootServicesCode of
75 Flat32Start: ; protected mode entry point
85 add edi, EnableExecuteDisableLocation
87 jz SkipEnableExecuteDisable
90 ; Enable IA32 PAE execute disable
111 SkipEnableExecuteDisable:
113 add edi, InitFlagLocation
114 cmp dword [edi], 1 ; 1 == ApInitConfig
117 ; Increment the number of APs executing here as early as possible
118 ; This is decremented in C code when AP is finished executing
120 add edi, NumApsExecutingLocation
125 add edi, LockLocation
126 mov eax, NotVacantFlag
130 cmp eax, NotVacantFlag
134 add ecx, ApIndexLocation
143 add edi, StackSizeLocation
147 mul ecx ; EAX = StackSize * (CpuNumber + 1)
149 add edi, StackStartAddressLocation
158 jb NoX2Apic ; CPUID level below CPUID_EXTENDED_TOPOLOGY
164 jz NoX2Apic ; CPUID.0BH:EBX[15:0] is zero
166 ; Processor is x2APIC capable; 32-bit x2APIC ID is already in EDX
167 jmp GetProcessorNumber
170 ; Processor is not x2APIC capable, so get 8-bit APIC ID
178 ; Get processor number for this AP
179 ; Note that BSP may become an AP due to SwitchBsp()
182 lea eax, [esi + CpuInfoLocation]
186 cmp [edi], edx ; APIC ID match?
190 jmp GetNextProcNumber
196 push ebp ; push BIST data at top of AP stack
197 xor ebp, ebp ; clear ebp for call stack trace
201 mov eax, ASM_PFX(InitializeFloatingPointUnits)
202 call eax ; Call assembly function to initialize FPU per UEFI spec
204 push ebx ; Push ApIndex
206 add eax, LockLocation
207 push eax ; push address of exchange info data buffer
210 add edi, ApProcedureLocation
213 call eax ; Invoke C function
215 jmp $ ; Never reach here
216 RendezvousFunnelProcEnd:
218 ;-------------------------------------------------------------------------------------
219 ; AsmRelocateApLoop (MwaitSupport, ApTargetCState, PmCodeSegment, TopOfApStack, CountTofinish);
220 ;-------------------------------------------------------------------------------------
221 global ASM_PFX(AsmRelocateApLoop)
222 ASM_PFX(AsmRelocateApLoop):
223 AsmRelocateApLoopStart:
225 mov esp, [eax + 16] ; TopOfApStack
226 push dword [eax] ; push return address for stack trace
229 mov ebx, [eax + 8] ; ApTargetCState
230 mov ecx, [eax + 4] ; MwaitSupport
231 mov eax, [eax + 20] ; CountTofinish
232 lock dec dword [eax] ; (*CountTofinish)--
233 cmp cl, 1 ; Check mwait-monitor support
241 mov eax, ebx ; Mwait Cx, Target C-State per eax[7:4]
249 AsmRelocateApLoopEnd:
251 ;-------------------------------------------------------------------------------------
252 ; AsmGetAddressMap (&AddressMap);
253 ;-------------------------------------------------------------------------------------
254 global ASM_PFX(AsmGetAddressMap)
255 ASM_PFX(AsmGetAddressMap):
260 mov dword [ebx], RendezvousFunnelProcStart
261 mov dword [ebx + 4h], Flat32Start - RendezvousFunnelProcStart
262 mov dword [ebx + 8h], RendezvousFunnelProcEnd - RendezvousFunnelProcStart
263 mov dword [ebx + 0Ch], AsmRelocateApLoopStart
264 mov dword [ebx + 10h], AsmRelocateApLoopEnd - AsmRelocateApLoopStart
265 mov dword [ebx + 14h], Flat32Start - RendezvousFunnelProcStart
270 ;-------------------------------------------------------------------------------------
271 ;AsmExchangeRole procedure follows. This procedure executed by current BSP, that is
272 ;about to become an AP. It switches it'stack with the current AP.
273 ;AsmExchangeRole (IN CPU_EXCHANGE_INFO *MyInfo, IN CPU_EXCHANGE_INFO *OthersInfo);
274 ;-------------------------------------------------------------------------------------
275 global ASM_PFX(AsmExchangeRole)
276 ASM_PFX(AsmExchangeRole):
277 ; DO NOT call other functions in this function, since 2 CPU may use 1 stack
278 ; at the same time. If 1 CPU try to call a function, stack will be corrupted.
282 ; esi contains MyInfo pointer
285 ; edi contains OthersInfo pointer
288 ;Store EFLAGS, GDTR and IDTR register to stack
291 push eax ; push cr4 firstly
298 ; Store the its StackPointer
301 ; update its switch state to STORED
302 mov byte [esi], CPU_SWITCH_STATE_STORED
305 ; wait until the other CPU finish storing its state
306 cmp byte [edi], CPU_SWITCH_STATE_STORED
309 jmp WaitForOtherStored
312 ; Since another CPU already stored its state, load them
319 ; load its future StackPointer
322 ; update the other CPU's switch state to LOADED
323 mov byte [edi], CPU_SWITCH_STATE_LOADED
326 ; wait until the other CPU finish loading new state,
327 ; otherwise the data in stack may corrupt
328 cmp byte [esi], CPU_SWITCH_STATE_LOADED
331 jmp WaitForOtherLoaded
334 ; since the other CPU already get the data it want, leave this procedure