]> git.proxmox.com Git - mirror_edk2.git/blob - UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm
UefiCpuPkg/MpInitLib: Enhance waiting for AP initialization logic.
[mirror_edk2.git] / UefiCpuPkg / Library / MpInitLib / X64 / MpFuncs.nasm
1 ;------------------------------------------------------------------------------ ;
2 ; Copyright (c) 2015 - 2017, 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.
7 ;
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.
10 ;
11 ; Module Name:
12 ;
13 ; MpFuncs.nasm
14 ;
15 ; Abstract:
16 ;
17 ; This is the assembly code for MP support
18 ;
19 ;-------------------------------------------------------------------------------
20
21 %include "MpEqu.inc"
22 extern ASM_PFX(InitializeFloatingPointUnits)
23
24 DEFAULT REL
25
26 SECTION .text
27
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
33 ;IS IN MACHINE CODE.
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
40
41 BITS 16
42 mov ebp, eax ; Save BIST information
43
44 mov ax, cs
45 mov ds, ax
46 mov es, ax
47 mov ss, ax
48 xor ax, ax
49 mov fs, ax
50 mov gs, ax
51
52 mov si, BufferStartLocation
53 mov ebx, [si]
54
55 mov di, ModeOffsetLocation
56 mov eax, [di]
57 mov di, CodeSegmentLocation
58 mov edx, [di]
59 mov di, ax
60 sub di, 02h
61 mov [di],dx ; Patch long mode CS
62 sub di, 04h
63 add eax, ebx
64 mov [di],eax ; Patch address
65
66 mov si, GdtrLocation
67 o32 lgdt [cs:si]
68
69 mov si, IdtrLocation
70 o32 lidt [cs:si]
71
72 mov si, EnableExecuteDisableLocation
73 cmp byte [si], 0
74 jz SkipEnableExecuteDisableBit
75
76 ;
77 ; Enable execute disable bit
78 ;
79 mov ecx, 0c0000080h ; EFER MSR number
80 rdmsr ; Read EFER
81 bts eax, 11 ; Enable Execute Disable Bit
82 wrmsr ; Write EFER
83
84 SkipEnableExecuteDisableBit:
85
86 mov di, DataSegmentLocation
87 mov edi, [di] ; Save long mode DS in edi
88
89 mov si, Cr3Location ; Save CR3 in ecx
90 mov ecx, [si]
91
92 xor ax, ax
93 mov ds, ax ; Clear data segment
94
95 mov eax, cr0 ; Get control register 0
96 or eax, 000000003h ; Set PE bit (bit #0) & MP
97 mov cr0, eax
98
99 mov eax, cr4
100 bts eax, 5
101 mov cr4, eax
102
103 mov cr3, ecx ; Load CR3
104
105 mov ecx, 0c0000080h ; EFER MSR number
106 rdmsr ; Read EFER
107 bts eax, 8 ; Set LME=1
108 wrmsr ; Write EFER
109
110 mov eax, cr0 ; Read CR0
111 bts eax, 31 ; Set PG=1
112 mov cr0, eax ; Write CR0
113
114 jmp 0:strict dword 0 ; far jump to long mode
115 BITS 64
116 LongModeStart:
117 mov eax, edi
118 mov ds, ax
119 mov es, ax
120 mov ss, ax
121
122 mov esi, ebx
123 lea edi, [esi + InitFlagLocation]
124 cmp qword [edi], 1 ; ApInitConfig
125 jnz GetApicId
126
127 ; Increment the number of APs executing here as early as possible
128 ; This is decremented in C code when AP is finished executing
129 mov edi, esi
130 add edi, NumApsExecutingLocation
131 lock inc dword [edi]
132
133 ; AP init
134 mov edi, esi
135 add edi, LockLocation
136 mov rax, NotVacantFlag
137
138 TestLock:
139 xchg qword [edi], rax
140 cmp rax, NotVacantFlag
141 jz TestLock
142
143 lea ecx, [esi + ApIndexLocation]
144 inc dword [ecx]
145 mov ebx, [ecx]
146
147 Releaselock:
148 mov rax, VacantFlag
149 xchg qword [edi], rax
150 ; program stack
151 mov edi, esi
152 add edi, StackSizeLocation
153 mov eax, dword [edi]
154 mov ecx, ebx
155 inc ecx
156 mul ecx ; EAX = StackSize * (CpuNumber + 1)
157 mov edi, esi
158 add edi, StackStartAddressLocation
159 add rax, qword [edi]
160 mov rsp, rax
161 jmp CProcedureInvoke
162
163 GetApicId:
164 mov eax, 0
165 cpuid
166 cmp eax, 0bh
167 jb NoX2Apic ; CPUID level below CPUID_EXTENDED_TOPOLOGY
168
169 mov eax, 0bh
170 xor ecx, ecx
171 cpuid
172 test ebx, 0ffffh
173 jz NoX2Apic ; CPUID.0BH:EBX[15:0] is zero
174
175 ; Processor is x2APIC capable; 32-bit x2APIC ID is already in EDX
176 jmp GetProcessorNumber
177
178 NoX2Apic:
179 ; Processor is not x2APIC capable, so get 8-bit APIC ID
180 mov eax, 1
181 cpuid
182 shr ebx, 24
183 mov edx, ebx
184
185 GetProcessorNumber:
186 ;
187 ; Get processor number for this AP
188 ; Note that BSP may become an AP due to SwitchBsp()
189 ;
190 xor ebx, ebx
191 lea eax, [esi + CpuInfoLocation]
192 mov edi, [eax]
193
194 GetNextProcNumber:
195 cmp dword [edi], edx ; APIC ID match?
196 jz ProgramStack
197 add edi, 20
198 inc ebx
199 jmp GetNextProcNumber
200
201 ProgramStack:
202 mov rsp, qword [edi + 12]
203
204 CProcedureInvoke:
205 push rbp ; Push BIST data at top of AP stack
206 xor rbp, rbp ; Clear ebp for call stack trace
207 push rbp
208 mov rbp, rsp
209
210 mov rax, qword [esi + InitializeFloatingPointUnitsAddress]
211 sub rsp, 20h
212 call rax ; Call assembly function to initialize FPU per UEFI spec
213 add rsp, 20h
214
215 mov edx, ebx ; edx is ApIndex
216 mov ecx, esi
217 add ecx, LockLocation ; rcx is address of exchange info data buffer
218
219 mov edi, esi
220 add edi, ApProcedureLocation
221 mov rax, qword [edi]
222
223 sub rsp, 20h
224 call rax ; Invoke C function
225 add rsp, 20h
226 jmp $ ; Should never reach here
227
228 RendezvousFunnelProcEnd:
229
230 ;-------------------------------------------------------------------------------------
231 ; AsmRelocateApLoop (MwaitSupport, ApTargetCState, PmCodeSegment, TopOfApStack, CountTofinish);
232 ;-------------------------------------------------------------------------------------
233 global ASM_PFX(AsmRelocateApLoop)
234 ASM_PFX(AsmRelocateApLoop):
235 AsmRelocateApLoopStart:
236 mov rax, [rsp + 40] ; CountTofinish
237 lock dec dword [rax] ; (*CountTofinish)--
238 mov rsp, r9
239 push rcx
240 push rdx
241
242 lea rsi, [PmEntry] ; rsi <- The start address of transition code
243
244 push r8
245 push rsi
246 DB 0x48
247 retf
248 BITS 32
249 PmEntry:
250 mov eax, cr0
251 btr eax, 31 ; Clear CR0.PG
252 mov cr0, eax ; Disable paging and caches
253
254 mov ebx, edx ; Save EntryPoint to rbx, for rdmsr will overwrite rdx
255 mov ecx, 0xc0000080
256 rdmsr
257 and ah, ~ 1 ; Clear LME
258 wrmsr
259 mov eax, cr4
260 and al, ~ (1 << 5) ; Clear PAE
261 mov cr4, eax
262
263 pop edx
264 add esp, 4
265 pop ecx,
266 add esp, 4
267 cmp cl, 1 ; Check mwait-monitor support
268 jnz HltLoop
269 mov ebx, edx ; Save C-State to ebx
270 MwaitLoop:
271 mov eax, esp ; Set Monitor Address
272 xor ecx, ecx ; ecx = 0
273 xor edx, edx ; edx = 0
274 monitor
275 mov eax, ebx ; Mwait Cx, Target C-State per eax[7:4]
276 shl eax, 4
277 mwait
278 jmp MwaitLoop
279 HltLoop:
280 cli
281 hlt
282 jmp HltLoop
283 BITS 64
284 AsmRelocateApLoopEnd:
285
286 ;-------------------------------------------------------------------------------------
287 ; AsmGetAddressMap (&AddressMap);
288 ;-------------------------------------------------------------------------------------
289 global ASM_PFX(AsmGetAddressMap)
290 ASM_PFX(AsmGetAddressMap):
291 lea rax, [ASM_PFX(RendezvousFunnelProc)]
292 mov qword [rcx], rax
293 mov qword [rcx + 8h], LongModeStart - RendezvousFunnelProcStart
294 mov qword [rcx + 10h], RendezvousFunnelProcEnd - RendezvousFunnelProcStart
295 lea rax, [ASM_PFX(AsmRelocateApLoop)]
296 mov qword [rcx + 18h], rax
297 mov qword [rcx + 20h], AsmRelocateApLoopEnd - AsmRelocateApLoopStart
298 ret
299
300 ;-------------------------------------------------------------------------------------
301 ;AsmExchangeRole procedure follows. This procedure executed by current BSP, that is
302 ;about to become an AP. It switches its stack with the current AP.
303 ;AsmExchangeRole (IN CPU_EXCHANGE_INFO *MyInfo, IN CPU_EXCHANGE_INFO *OthersInfo);
304 ;-------------------------------------------------------------------------------------
305 global ASM_PFX(AsmExchangeRole)
306 ASM_PFX(AsmExchangeRole):
307 ; DO NOT call other functions in this function, since 2 CPU may use 1 stack
308 ; at the same time. If 1 CPU try to call a function, stack will be corrupted.
309
310 push rax
311 push rbx
312 push rcx
313 push rdx
314 push rsi
315 push rdi
316 push rbp
317 push r8
318 push r9
319 push r10
320 push r11
321 push r12
322 push r13
323 push r14
324 push r15
325
326 mov rax, cr0
327 push rax
328
329 mov rax, cr4
330 push rax
331
332 ; rsi contains MyInfo pointer
333 mov rsi, rcx
334
335 ; rdi contains OthersInfo pointer
336 mov rdi, rdx
337
338 ;Store EFLAGS, GDTR and IDTR regiter to stack
339 pushfq
340 sgdt [rsi + 16]
341 sidt [rsi + 26]
342
343 ; Store the its StackPointer
344 mov [rsi + 8], rsp
345
346 ; update its switch state to STORED
347 mov byte [rsi], CPU_SWITCH_STATE_STORED
348
349 WaitForOtherStored:
350 ; wait until the other CPU finish storing its state
351 cmp byte [rdi], CPU_SWITCH_STATE_STORED
352 jz OtherStored
353 pause
354 jmp WaitForOtherStored
355
356 OtherStored:
357 ; Since another CPU already stored its state, load them
358 ; load GDTR value
359 lgdt [rdi + 16]
360
361 ; load IDTR value
362 lidt [rdi + 26]
363
364 ; load its future StackPointer
365 mov rsp, [rdi + 8]
366
367 ; update the other CPU's switch state to LOADED
368 mov byte [rdi], CPU_SWITCH_STATE_LOADED
369
370 WaitForOtherLoaded:
371 ; wait until the other CPU finish loading new state,
372 ; otherwise the data in stack may corrupt
373 cmp byte [rsi], CPU_SWITCH_STATE_LOADED
374 jz OtherLoaded
375 pause
376 jmp WaitForOtherLoaded
377
378 OtherLoaded:
379 ; since the other CPU already get the data it want, leave this procedure
380 popfq
381
382 pop rax
383 mov cr4, rax
384
385 pop rax
386 mov cr0, rax
387
388 pop r15
389 pop r14
390 pop r13
391 pop r12
392 pop r11
393 pop r10
394 pop r9
395 pop r8
396 pop rbp
397 pop rdi
398 pop rsi
399 pop rdx
400 pop rcx
401 pop rbx
402 pop rax
403
404 ret