]> git.proxmox.com Git - mirror_edk2.git/blob - UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm
UefiCpuPkg/MpInitLib/X64/MpFuncs.nasm: fix fatal typo
[mirror_edk2.git] / UefiCpuPkg / Library / MpInitLib / X64 / MpFuncs.nasm
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.
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 ; AP init
128 mov edi, esi
129 add edi, LockLocation
130 mov rax, NotVacantFlag
131
132 TestLock:
133 xchg qword [edi], rax
134 cmp rax, NotVacantFlag
135 jz TestLock
136
137 lea ecx, [esi + NumApsExecutingLocation]
138 inc dword [ecx]
139 mov ebx, [ecx]
140
141 Releaselock:
142 mov rax, VacantFlag
143 xchg qword [edi], rax
144 ; program stack
145 mov edi, esi
146 add edi, StackSizeLocation
147 mov eax, dword [edi]
148 mov ecx, ebx
149 inc ecx
150 mul ecx ; EAX = StackSize * (CpuNumber + 1)
151 mov edi, esi
152 add edi, StackStartAddressLocation
153 add rax, qword [edi]
154 mov rsp, rax
155 jmp CProcedureInvoke
156
157 GetApicId:
158 mov eax, 0
159 cpuid
160 cmp eax, 0bh
161 jnb X2Apic
162 ; Processor is not x2APIC capable, so get 8-bit APIC ID
163 mov eax, 1
164 cpuid
165 shr ebx, 24
166 mov edx, ebx
167 jmp GetProcessorNumber
168
169 X2Apic:
170 ; Processor is x2APIC capable, so get 32-bit x2APIC ID
171 mov eax, 0bh
172 xor ecx, ecx
173 cpuid
174 ; edx save x2APIC ID
175
176 GetProcessorNumber:
177 ;
178 ; Get processor number for this AP
179 ; Note that BSP may become an AP due to SwitchBsp()
180 ;
181 xor ebx, ebx
182 lea eax, [esi + CpuInfoLocation]
183 mov edi, [eax]
184
185 GetNextProcNumber:
186 cmp dword [edi], edx ; APIC ID match?
187 jz ProgramStack
188 add edi, 16
189 inc ebx
190 jmp GetNextProcNumber
191
192 ProgramStack:
193 xor rsp, rsp
194 mov esp, dword [edi + 12]
195
196 CProcedureInvoke:
197 push rbp ; Push BIST data at top of AP stack
198 xor rbp, rbp ; Clear ebp for call stack trace
199 push rbp
200 mov rbp, rsp
201
202 mov rax, ASM_PFX(InitializeFloatingPointUnits)
203 sub rsp, 20h
204 call rax ; Call assembly function to initialize FPU per UEFI spec
205 add rsp, 20h
206
207 mov edx, ebx ; edx is NumApsExecuting
208 mov ecx, esi
209 add ecx, LockLocation ; rcx is address of exchange info data buffer
210
211 mov edi, esi
212 add edi, ApProcedureLocation
213 mov rax, qword [edi]
214
215 sub rsp, 20h
216 call rax ; Invoke C function
217 add rsp, 20h
218 jmp $ ; Should never reach here
219
220 RendezvousFunnelProcEnd:
221
222 ;-------------------------------------------------------------------------------------
223 ; AsmRelocateApLoop (MwaitSupport, ApTargetCState, PmCodeSegment);
224 ;-------------------------------------------------------------------------------------
225 global ASM_PFX(AsmRelocateApLoop)
226 ASM_PFX(AsmRelocateApLoop):
227 AsmRelocateApLoopStart:
228 push rcx
229 push rdx
230
231 lea rsi, [PmEntry] ; rsi <- The start address of transition code
232
233 push r8
234 push rsi
235 DB 0x48
236 retf
237 BITS 32
238 PmEntry:
239 mov eax, cr0
240 btr eax, 31 ; Clear CR0.PG
241 mov cr0, eax ; Disable paging and caches
242
243 mov ebx, edx ; Save EntryPoint to rbx, for rdmsr will overwrite rdx
244 mov ecx, 0xc0000080
245 rdmsr
246 and ah, ~ 1 ; Clear LME
247 wrmsr
248 mov eax, cr4
249 and al, ~ (1 << 5) ; Clear PAE
250 mov cr4, eax
251
252 pop edx
253 add esp, 4
254 pop ecx,
255 add esp, 4
256 cmp cl, 1 ; Check mwait-monitor support
257 jnz HltLoop
258 mov ebx, edx ; Save C-State to ebx
259 MwaitLoop:
260 mov eax, esp ; Set Monitor Address
261 xor ecx, ecx ; ecx = 0
262 xor edx, edx ; edx = 0
263 monitor
264 shl ebx, 4
265 mov eax, ebx ; Mwait Cx, Target C-State per eax[7:4]
266 mwait
267 jmp MwaitLoop
268 HltLoop:
269 cli
270 hlt
271 jmp HltLoop
272 ret
273 BITS 64
274 AsmRelocateApLoopEnd:
275
276 ;-------------------------------------------------------------------------------------
277 ; AsmGetAddressMap (&AddressMap);
278 ;-------------------------------------------------------------------------------------
279 global ASM_PFX(AsmGetAddressMap)
280 ASM_PFX(AsmGetAddressMap):
281 mov rax, ASM_PFX(RendezvousFunnelProc)
282 mov qword [rcx], rax
283 mov qword [rcx + 8h], LongModeStart - RendezvousFunnelProcStart
284 mov qword [rcx + 10h], RendezvousFunnelProcEnd - RendezvousFunnelProcStart
285 mov rax, ASM_PFX(AsmRelocateApLoop)
286 mov qword [rcx + 18h], rax
287 mov qword [rcx + 20h], AsmRelocateApLoopEnd - AsmRelocateApLoopStart
288 ret
289
290 ;-------------------------------------------------------------------------------------
291 ;AsmExchangeRole procedure follows. This procedure executed by current BSP, that is
292 ;about to become an AP. It switches its stack with the current AP.
293 ;AsmExchangeRole (IN CPU_EXCHANGE_INFO *MyInfo, IN CPU_EXCHANGE_INFO *OthersInfo);
294 ;-------------------------------------------------------------------------------------
295 global ASM_PFX(AsmExchangeRole)
296 ASM_PFX(AsmExchangeRole):
297 ; DO NOT call other functions in this function, since 2 CPU may use 1 stack
298 ; at the same time. If 1 CPU try to call a function, stack will be corrupted.
299
300 push rax
301 push rbx
302 push rcx
303 push rdx
304 push rsi
305 push rdi
306 push rbp
307 push r8
308 push r9
309 push r10
310 push r11
311 push r12
312 push r13
313 push r14
314 push r15
315
316 mov rax, cr0
317 push rax
318
319 mov rax, cr4
320 push rax
321
322 ; rsi contains MyInfo pointer
323 mov rsi, rcx
324
325 ; rdi contains OthersInfo pointer
326 mov rdi, rdx
327
328 ;Store EFLAGS, GDTR and IDTR regiter to stack
329 pushfq
330 sgdt [rsi + 16]
331 sidt [rsi + 26]
332
333 ; Store the its StackPointer
334 mov [rsi + 8], rsp
335
336 ; update its switch state to STORED
337 mov byte [rsi], CPU_SWITCH_STATE_STORED
338
339 WaitForOtherStored:
340 ; wait until the other CPU finish storing its state
341 cmp byte [rdi], CPU_SWITCH_STATE_STORED
342 jz OtherStored
343 pause
344 jmp WaitForOtherStored
345
346 OtherStored:
347 ; Since another CPU already stored its state, load them
348 ; load GDTR value
349 lgdt [rdi + 16]
350
351 ; load IDTR value
352 lidt [rdi + 26]
353
354 ; load its future StackPointer
355 mov rsp, [rdi + 8]
356
357 ; update the other CPU's switch state to LOADED
358 mov byte [rdi], CPU_SWITCH_STATE_LOADED
359
360 WaitForOtherLoaded:
361 ; wait until the other CPU finish loading new state,
362 ; otherwise the data in stack may corrupt
363 cmp byte [rsi], CPU_SWITCH_STATE_LOADED
364 jz OtherLoaded
365 pause
366 jmp WaitForOtherLoaded
367
368 OtherLoaded:
369 ; since the other CPU already get the data it want, leave this procedure
370 popfq
371
372 pop rax
373 mov cr4, rax
374
375 pop rax
376 mov cr0, rax
377
378 pop r15
379 pop r14
380 pop r13
381 pop r12
382 pop r11
383 pop r10
384 pop r9
385 pop r8
386 pop rbp
387 pop rdi
388 pop rsi
389 pop rdx
390 pop rcx
391 pop rbx
392 pop rax
393
394 ret