]> git.proxmox.com Git - mirror_edk2.git/blob - UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm
UefiCpuPkg: Clean up source files
[mirror_edk2.git] / UefiCpuPkg / Library / MpInitLib / X64 / MpFuncs.nasm
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.
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 si, DataSegmentLocation
56 mov edx, [si]
57
58 ;
59 ; Get start address of 32-bit code in low memory (<1MB)
60 ;
61 mov edi, ModeTransitionMemoryLocation
62
63 mov si, GdtrLocation
64 o32 lgdt [cs:si]
65
66 mov si, IdtrLocation
67 o32 lidt [cs:si]
68
69 ;
70 ; Switch to protected mode
71 ;
72 mov eax, cr0 ; Get control register 0
73 or eax, 000000003h ; Set PE bit (bit #0) & MP
74 mov cr0, eax
75
76 ; Switch to 32-bit code (>1MB)
77 o32 jmp far [cs:di]
78
79 ;
80 ; Following code must be copied to memory with type of EfiBootServicesCode.
81 ; This is required if NX is enabled for EfiBootServicesCode of memory.
82 ;
83 BITS 32
84 Flat32Start: ; protected mode entry point
85 mov ds, dx
86 mov es, dx
87 mov fs, dx
88 mov gs, dx
89 mov ss, dx
90
91 ;
92 ; Enable execute disable bit
93 ;
94 mov esi, EnableExecuteDisableLocation
95 cmp byte [ebx + esi], 0
96 jz SkipEnableExecuteDisableBit
97
98 mov ecx, 0c0000080h ; EFER MSR number
99 rdmsr ; Read EFER
100 bts eax, 11 ; Enable Execute Disable Bit
101 wrmsr ; Write EFER
102
103 SkipEnableExecuteDisableBit:
104 ;
105 ; Enable PAE
106 ;
107 mov eax, cr4
108 bts eax, 5
109 mov cr4, eax
110
111 ;
112 ; Load page table
113 ;
114 mov esi, Cr3Location ; Save CR3 in ecx
115 mov ecx, [ebx + esi]
116 mov cr3, ecx ; Load CR3
117
118 ;
119 ; Enable long mode
120 ;
121 mov ecx, 0c0000080h ; EFER MSR number
122 rdmsr ; Read EFER
123 bts eax, 8 ; Set LME=1
124 wrmsr ; Write EFER
125
126 ;
127 ; Enable paging
128 ;
129 mov eax, cr0 ; Read CR0
130 bts eax, 31 ; Set PG=1
131 mov cr0, eax ; Write CR0
132
133 ;
134 ; Far jump to 64-bit code
135 ;
136 mov edi, ModeHighMemoryLocation
137 add edi, ebx
138 jmp far [edi]
139
140 BITS 64
141 LongModeStart:
142 mov esi, ebx
143 lea edi, [esi + InitFlagLocation]
144 cmp qword [edi], 1 ; ApInitConfig
145 jnz GetApicId
146
147 ; Increment the number of APs executing here as early as possible
148 ; This is decremented in C code when AP is finished executing
149 mov edi, esi
150 add edi, NumApsExecutingLocation
151 lock inc dword [edi]
152
153 ; AP init
154 mov edi, esi
155 add edi, LockLocation
156 mov rax, NotVacantFlag
157
158 TestLock:
159 xchg qword [edi], rax
160 cmp rax, NotVacantFlag
161 jz TestLock
162
163 lea ecx, [esi + ApIndexLocation]
164 inc dword [ecx]
165 mov ebx, [ecx]
166
167 Releaselock:
168 mov rax, VacantFlag
169 xchg qword [edi], rax
170 ; program stack
171 mov edi, esi
172 add edi, StackSizeLocation
173 mov eax, dword [edi]
174 mov ecx, ebx
175 inc ecx
176 mul ecx ; EAX = StackSize * (CpuNumber + 1)
177 mov edi, esi
178 add edi, StackStartAddressLocation
179 add rax, qword [edi]
180 mov rsp, rax
181 jmp CProcedureInvoke
182
183 GetApicId:
184 mov eax, 0
185 cpuid
186 cmp eax, 0bh
187 jb NoX2Apic ; CPUID level below CPUID_EXTENDED_TOPOLOGY
188
189 mov eax, 0bh
190 xor ecx, ecx
191 cpuid
192 test ebx, 0ffffh
193 jz NoX2Apic ; CPUID.0BH:EBX[15:0] is zero
194
195 ; Processor is x2APIC capable; 32-bit x2APIC ID is already in EDX
196 jmp GetProcessorNumber
197
198 NoX2Apic:
199 ; Processor is not x2APIC capable, so get 8-bit APIC ID
200 mov eax, 1
201 cpuid
202 shr ebx, 24
203 mov edx, ebx
204
205 GetProcessorNumber:
206 ;
207 ; Get processor number for this AP
208 ; Note that BSP may become an AP due to SwitchBsp()
209 ;
210 xor ebx, ebx
211 lea eax, [esi + CpuInfoLocation]
212 mov edi, [eax]
213
214 GetNextProcNumber:
215 cmp dword [edi], edx ; APIC ID match?
216 jz ProgramStack
217 add edi, 20
218 inc ebx
219 jmp GetNextProcNumber
220
221 ProgramStack:
222 mov rsp, qword [edi + 12]
223
224 CProcedureInvoke:
225 push rbp ; Push BIST data at top of AP stack
226 xor rbp, rbp ; Clear ebp for call stack trace
227 push rbp
228 mov rbp, rsp
229
230 mov rax, qword [esi + InitializeFloatingPointUnitsAddress]
231 sub rsp, 20h
232 call rax ; Call assembly function to initialize FPU per UEFI spec
233 add rsp, 20h
234
235 mov edx, ebx ; edx is ApIndex
236 mov ecx, esi
237 add ecx, LockLocation ; rcx is address of exchange info data buffer
238
239 mov edi, esi
240 add edi, ApProcedureLocation
241 mov rax, qword [edi]
242
243 sub rsp, 20h
244 call rax ; Invoke C function
245 add rsp, 20h
246 jmp $ ; Should never reach here
247
248 RendezvousFunnelProcEnd:
249
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)--
259 mov rsp, r9
260 push rcx
261 push rdx
262
263 lea rsi, [PmEntry] ; rsi <- The start address of transition code
264
265 push r8
266 push rsi
267 DB 0x48
268 retf
269 BITS 32
270 PmEntry:
271 mov eax, cr0
272 btr eax, 31 ; Clear CR0.PG
273 mov cr0, eax ; Disable paging and caches
274
275 mov ebx, edx ; Save EntryPoint to rbx, for rdmsr will overwrite rdx
276 mov ecx, 0xc0000080
277 rdmsr
278 and ah, ~ 1 ; Clear LME
279 wrmsr
280 mov eax, cr4
281 and al, ~ (1 << 5) ; Clear PAE
282 mov cr4, eax
283
284 pop edx
285 add esp, 4
286 pop ecx,
287 add esp, 4
288 cmp cl, 1 ; Check mwait-monitor support
289 jnz HltLoop
290 mov ebx, edx ; Save C-State to ebx
291 MwaitLoop:
292 cli
293 mov eax, esp ; Set Monitor Address
294 xor ecx, ecx ; ecx = 0
295 xor edx, edx ; edx = 0
296 monitor
297 mov eax, ebx ; Mwait Cx, Target C-State per eax[7:4]
298 shl eax, 4
299 mwait
300 jmp MwaitLoop
301 HltLoop:
302 cli
303 hlt
304 jmp HltLoop
305 BITS 64
306 AsmRelocateApLoopEnd:
307
308 ;-------------------------------------------------------------------------------------
309 ; AsmGetAddressMap (&AddressMap);
310 ;-------------------------------------------------------------------------------------
311 global ASM_PFX(AsmGetAddressMap)
312 ASM_PFX(AsmGetAddressMap):
313 lea rax, [ASM_PFX(RendezvousFunnelProc)]
314 mov qword [rcx], rax
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
321 ret
322
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.
332
333 push rax
334 push rbx
335 push rcx
336 push rdx
337 push rsi
338 push rdi
339 push rbp
340 push r8
341 push r9
342 push r10
343 push r11
344 push r12
345 push r13
346 push r14
347 push r15
348
349 mov rax, cr0
350 push rax
351
352 mov rax, cr4
353 push rax
354
355 ; rsi contains MyInfo pointer
356 mov rsi, rcx
357
358 ; rdi contains OthersInfo pointer
359 mov rdi, rdx
360
361 ;Store EFLAGS, GDTR and IDTR regiter to stack
362 pushfq
363 sgdt [rsi + 16]
364 sidt [rsi + 26]
365
366 ; Store the its StackPointer
367 mov [rsi + 8], rsp
368
369 ; update its switch state to STORED
370 mov byte [rsi], CPU_SWITCH_STATE_STORED
371
372 WaitForOtherStored:
373 ; wait until the other CPU finish storing its state
374 cmp byte [rdi], CPU_SWITCH_STATE_STORED
375 jz OtherStored
376 pause
377 jmp WaitForOtherStored
378
379 OtherStored:
380 ; Since another CPU already stored its state, load them
381 ; load GDTR value
382 lgdt [rdi + 16]
383
384 ; load IDTR value
385 lidt [rdi + 26]
386
387 ; load its future StackPointer
388 mov rsp, [rdi + 8]
389
390 ; update the other CPU's switch state to LOADED
391 mov byte [rdi], CPU_SWITCH_STATE_LOADED
392
393 WaitForOtherLoaded:
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
397 jz OtherLoaded
398 pause
399 jmp WaitForOtherLoaded
400
401 OtherLoaded:
402 ; since the other CPU already get the data it want, leave this procedure
403 popfq
404
405 pop rax
406 mov cr4, rax
407
408 pop rax
409 mov cr0, rax
410
411 pop r15
412 pop r14
413 pop r13
414 pop r12
415 pop r11
416 pop r10
417 pop r9
418 pop r8
419 pop rbp
420 pop rdi
421 pop rsi
422 pop rdx
423 pop rcx
424 pop rbx
425 pop rax
426
427 ret