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