1 ;------------------------------------------------------------------------------ ;
2 ; Copyright (c) 2015 - 2018, 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 ASM_PFX(InitializeFloatingPointUnits)
28 ;-------------------------------------------------------------------------------------
29 ;RendezvousFunnelProc procedure follows. All APs execute their procedure. This
30 ;procedure serializes all the AP processors through an Init sequence. It must be
31 ;noted that APs arrive here very raw...ie: real mode, no stack.
32 ;ALSO THIS PROCEDURE IS EXECUTED BY APs ONLY ON 16 BIT MODE. HENCE THIS PROC
34 ;-------------------------------------------------------------------------------------
35 global ASM_PFX(RendezvousFunnelProc)
36 ASM_PFX(RendezvousFunnelProc):
37 RendezvousFunnelProcStart:
38 ; At this point CS = 0x(vv00) and ip= 0x0.
39 ; Save BIST information to ebp firstly
42 mov ebp, eax ; Save BIST information
52 mov si, BufferStartLocation
55 mov si, DataSegmentLocation
59 ; Get start address of 32-bit code in low memory (<1MB)
61 mov edi, ModeTransitionMemoryLocation
70 ; Switch to protected mode
72 mov eax, cr0 ; Get control register 0
73 or eax, 000000003h ; Set PE bit (bit #0) & MP
76 ; Switch to 32-bit code (>1MB)
80 ; Following code must be copied to memory with type of EfiBootServicesCode.
81 ; This is required if NX is enabled for EfiBootServicesCode of memory.
84 Flat32Start: ; protected mode entry point
92 ; Enable execute disable bit
94 mov esi, EnableExecuteDisableLocation
95 cmp byte [ebx + esi], 0
96 jz SkipEnableExecuteDisableBit
98 mov ecx, 0c0000080h ; EFER MSR number
100 bts eax, 11 ; Enable Execute Disable Bit
103 SkipEnableExecuteDisableBit:
114 mov esi, Cr3Location ; Save CR3 in ecx
116 mov cr3, ecx ; Load CR3
121 mov ecx, 0c0000080h ; EFER MSR number
123 bts eax, 8 ; Set LME=1
129 mov eax, cr0 ; Read CR0
130 bts eax, 31 ; Set PG=1
131 mov cr0, eax ; Write CR0
134 ; Far jump to 64-bit code
136 mov edi, ModeHighMemoryLocation
143 lea edi, [esi + InitFlagLocation]
144 cmp qword [edi], 1 ; ApInitConfig
147 ; Increment the number of APs executing here as early as possible
148 ; This is decremented in C code when AP is finished executing
150 add edi, NumApsExecutingLocation
155 add edi, LockLocation
156 mov rax, NotVacantFlag
159 xchg qword [edi], rax
160 cmp rax, NotVacantFlag
163 lea ecx, [esi + ApIndexLocation]
169 xchg qword [edi], rax
172 add edi, StackSizeLocation
176 mul ecx ; EAX = StackSize * (CpuNumber + 1)
178 add edi, StackStartAddressLocation
187 jb NoX2Apic ; CPUID level below CPUID_EXTENDED_TOPOLOGY
193 jz NoX2Apic ; CPUID.0BH:EBX[15:0] is zero
195 ; Processor is x2APIC capable; 32-bit x2APIC ID is already in EDX
196 jmp GetProcessorNumber
199 ; Processor is not x2APIC capable, so get 8-bit APIC ID
207 ; Get processor number for this AP
208 ; Note that BSP may become an AP due to SwitchBsp()
211 lea eax, [esi + CpuInfoLocation]
215 cmp dword [edi], edx ; APIC ID match?
219 jmp GetNextProcNumber
222 mov rsp, qword [edi + 12]
225 push rbp ; Push BIST data at top of AP stack
226 xor rbp, rbp ; Clear ebp for call stack trace
230 mov rax, qword [esi + InitializeFloatingPointUnitsAddress]
232 call rax ; Call assembly function to initialize FPU per UEFI spec
235 mov edx, ebx ; edx is ApIndex
237 add ecx, LockLocation ; rcx is address of exchange info data buffer
240 add edi, ApProcedureLocation
244 call rax ; Invoke C function
246 jmp $ ; Should never reach here
248 RendezvousFunnelProcEnd:
250 ;-------------------------------------------------------------------------------------
251 ; AsmRelocateApLoop (MwaitSupport, ApTargetCState, PmCodeSegment, TopOfApStack, CountTofinish);
252 ;-------------------------------------------------------------------------------------
253 global ASM_PFX(AsmRelocateApLoop)
254 ASM_PFX(AsmRelocateApLoop):
255 AsmRelocateApLoopStart:
256 cli ; Disable interrupt before switching to 32-bit mode
257 mov rax, [rsp + 40] ; CountTofinish
258 lock dec dword [rax] ; (*CountTofinish)--
263 lea rsi, [PmEntry] ; rsi <- The start address of transition code
272 btr eax, 31 ; Clear CR0.PG
273 mov cr0, eax ; Disable paging and caches
275 mov ebx, edx ; Save EntryPoint to rbx, for rdmsr will overwrite rdx
278 and ah, ~ 1 ; Clear LME
281 and al, ~ (1 << 5) ; Clear PAE
288 cmp cl, 1 ; Check mwait-monitor support
290 mov ebx, edx ; Save C-State to ebx
293 mov eax, esp ; Set Monitor Address
294 xor ecx, ecx ; ecx = 0
295 xor edx, edx ; edx = 0
297 mov eax, ebx ; Mwait Cx, Target C-State per eax[7:4]
306 AsmRelocateApLoopEnd:
308 ;-------------------------------------------------------------------------------------
309 ; AsmGetAddressMap (&AddressMap);
310 ;-------------------------------------------------------------------------------------
311 global ASM_PFX(AsmGetAddressMap)
312 ASM_PFX(AsmGetAddressMap):
313 lea rax, [ASM_PFX(RendezvousFunnelProc)]
315 mov qword [rcx + 8h], LongModeStart - RendezvousFunnelProcStart
316 mov qword [rcx + 10h], RendezvousFunnelProcEnd - RendezvousFunnelProcStart
317 lea rax, [ASM_PFX(AsmRelocateApLoop)]
318 mov qword [rcx + 18h], rax
319 mov qword [rcx + 20h], AsmRelocateApLoopEnd - AsmRelocateApLoopStart
320 mov qword [rcx + 28h], Flat32Start - RendezvousFunnelProcStart
323 ;-------------------------------------------------------------------------------------
324 ;AsmExchangeRole procedure follows. This procedure executed by current BSP, that is
325 ;about to become an AP. It switches its stack with the current AP.
326 ;AsmExchangeRole (IN CPU_EXCHANGE_INFO *MyInfo, IN CPU_EXCHANGE_INFO *OthersInfo);
327 ;-------------------------------------------------------------------------------------
328 global ASM_PFX(AsmExchangeRole)
329 ASM_PFX(AsmExchangeRole):
330 ; DO NOT call other functions in this function, since 2 CPU may use 1 stack
331 ; at the same time. If 1 CPU try to call a function, stack will be corrupted.
355 ; rsi contains MyInfo pointer
358 ; rdi contains OthersInfo pointer
361 ;Store EFLAGS, GDTR and IDTR regiter to stack
366 ; Store the its StackPointer
369 ; update its switch state to STORED
370 mov byte [rsi], CPU_SWITCH_STATE_STORED
373 ; wait until the other CPU finish storing its state
374 cmp byte [rdi], CPU_SWITCH_STATE_STORED
377 jmp WaitForOtherStored
380 ; Since another CPU already stored its state, load them
387 ; load its future StackPointer
390 ; update the other CPU's switch state to LOADED
391 mov byte [rdi], CPU_SWITCH_STATE_LOADED
394 ; wait until the other CPU finish loading new state,
395 ; otherwise the data in stack may corrupt
396 cmp byte [rsi], CPU_SWITCH_STATE_LOADED
399 jmp WaitForOtherLoaded
402 ; since the other CPU already get the data it want, leave this procedure