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