]> git.proxmox.com Git - mirror_edk2.git/blob - UefiCpuPkg/Library/MpInitLib/Ia32/MpFuncs.nasm
34b8705adb5145a0313dc168353b8ca23cf6fb92
[mirror_edk2.git] / UefiCpuPkg / Library / MpInitLib / Ia32 / MpFuncs.nasm
1 ;------------------------------------------------------------------------------ ;
2 ; Copyright (c) 2015 - 2018, 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 SECTION .text
19
20 ;-------------------------------------------------------------------------------------
21 ;RendezvousFunnelProc procedure follows. All APs execute their procedure. This
22 ;procedure serializes all the AP processors through an Init sequence. It must be
23 ;noted that APs arrive here very raw...ie: real mode, no stack.
24 ;ALSO THIS PROCEDURE IS EXECUTED BY APs ONLY ON 16 BIT MODE. HENCE THIS PROC
25 ;IS IN MACHINE CODE.
26 ;-------------------------------------------------------------------------------------
27 global ASM_PFX(RendezvousFunnelProc)
28 ASM_PFX(RendezvousFunnelProc):
29 RendezvousFunnelProcStart:
30 ; At this point CS = 0x(vv00) and ip= 0x0.
31 BITS 16
32 mov ebp, eax ; save BIST information
33
34 mov ax, cs
35 mov ds, ax
36 mov es, ax
37 mov ss, ax
38 xor ax, ax
39 mov fs, ax
40 mov gs, ax
41
42 mov si, BufferStartLocation
43 mov ebx, [si]
44
45 mov si, DataSegmentLocation
46 mov edx, [si]
47
48 ;
49 ; Get start address of 32-bit code in low memory (<1MB)
50 ;
51 mov edi, ModeTransitionMemoryLocation
52
53 mov si, GdtrLocation
54 o32 lgdt [cs:si]
55
56 mov si, IdtrLocation
57 o32 lidt [cs:si]
58
59 ;
60 ; Switch to protected mode
61 ;
62 mov eax, cr0 ; Get control register 0
63 or eax, 000000003h ; Set PE bit (bit #0) & MP
64 mov cr0, eax
65
66 ; Switch to 32-bit code in executable memory (>1MB)
67 o32 jmp far [cs:di]
68
69 ;
70 ; Following code may be copied to memory with type of EfiBootServicesCode.
71 ; This is required at DXE phase if NX is enabled for EfiBootServicesCode of
72 ; memory.
73 ;
74 BITS 32
75 Flat32Start: ; protected mode entry point
76 mov ds, dx
77 mov es, dx
78 mov fs, dx
79 mov gs, dx
80 mov ss, dx
81
82 mov esi, ebx
83
84 ; Increment the number of APs executing here as early as possible
85 ; This is decremented in C code when AP is finished executing
86 mov edi, esi
87 add edi, NumApsExecutingLocation
88 lock inc dword [edi]
89
90 mov edi, esi
91 add edi, EnableExecuteDisableLocation
92 cmp byte [edi], 0
93 jz SkipEnableExecuteDisable
94
95 ;
96 ; Enable IA32 PAE execute disable
97 ;
98
99 mov ecx, 0xc0000080
100 rdmsr
101 bts eax, 11
102 wrmsr
103
104 mov edi, esi
105 add edi, Cr3Location
106 mov eax, dword [edi]
107 mov cr3, eax
108
109 mov eax, cr4
110 bts eax, 5
111 mov cr4, eax
112
113 mov eax, cr0
114 bts eax, 31
115 mov cr0, eax
116
117 SkipEnableExecuteDisable:
118 mov edi, esi
119 add edi, InitFlagLocation
120 cmp dword [edi], 1 ; 1 == ApInitConfig
121 jnz GetApicId
122
123 ; AP init
124 mov edi, esi
125 add edi, LockLocation
126 mov eax, NotVacantFlag
127
128 TestLock:
129 xchg [edi], eax
130 cmp eax, NotVacantFlag
131 jz TestLock
132
133 mov ecx, esi
134 add ecx, ApIndexLocation
135 inc dword [ecx]
136 mov ebx, [ecx]
137
138 Releaselock:
139 mov eax, VacantFlag
140 xchg [edi], eax
141
142 mov edi, esi
143 add edi, StackSizeLocation
144 mov eax, [edi]
145 mov ecx, ebx
146 inc ecx
147 mul ecx ; EAX = StackSize * (CpuNumber + 1)
148 mov edi, esi
149 add edi, StackStartAddressLocation
150 add eax, [edi]
151 mov esp, eax
152 jmp CProcedureInvoke
153
154 GetApicId:
155 mov eax, 0
156 cpuid
157 cmp eax, 0bh
158 jb NoX2Apic ; CPUID level below CPUID_EXTENDED_TOPOLOGY
159
160 mov eax, 0bh
161 xor ecx, ecx
162 cpuid
163 test ebx, 0ffffh
164 jz NoX2Apic ; CPUID.0BH:EBX[15:0] is zero
165
166 ; Processor is x2APIC capable; 32-bit x2APIC ID is already in EDX
167 jmp GetProcessorNumber
168
169 NoX2Apic:
170 ; Processor is not x2APIC capable, so get 8-bit APIC ID
171 mov eax, 1
172 cpuid
173 shr ebx, 24
174 mov edx, ebx
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 [edi], edx ; APIC ID match?
187 jz ProgramStack
188 add edi, 20
189 inc ebx
190 jmp GetNextProcNumber
191
192 ProgramStack:
193 mov esp, [edi + 12]
194
195 CProcedureInvoke:
196 push ebp ; push BIST data at top of AP stack
197 xor ebp, ebp ; clear ebp for call stack trace
198 push ebp
199 mov ebp, esp
200
201 mov eax, ASM_PFX(InitializeFloatingPointUnits)
202 call eax ; Call assembly function to initialize FPU per UEFI spec
203
204 push ebx ; Push ApIndex
205 mov eax, esi
206 add eax, LockLocation
207 push eax ; push address of exchange info data buffer
208
209 mov edi, esi
210 add edi, ApProcedureLocation
211 mov eax, [edi]
212
213 call eax ; Invoke C function
214
215 jmp $ ; Never reach here
216 RendezvousFunnelProcEnd:
217
218 ;-------------------------------------------------------------------------------------
219 ; AsmRelocateApLoop (MwaitSupport, ApTargetCState, PmCodeSegment, TopOfApStack, CountTofinish);
220 ;-------------------------------------------------------------------------------------
221 global ASM_PFX(AsmRelocateApLoop)
222 ASM_PFX(AsmRelocateApLoop):
223 AsmRelocateApLoopStart:
224 mov eax, esp
225 mov esp, [eax + 16] ; TopOfApStack
226 push dword [eax] ; push return address for stack trace
227 push ebp
228 mov ebp, esp
229 mov ebx, [eax + 8] ; ApTargetCState
230 mov ecx, [eax + 4] ; MwaitSupport
231 mov eax, [eax + 20] ; CountTofinish
232 lock dec dword [eax] ; (*CountTofinish)--
233 cmp cl, 1 ; Check mwait-monitor support
234 jnz HltLoop
235 MwaitLoop:
236 cli
237 mov eax, esp
238 xor ecx, ecx
239 xor edx, edx
240 monitor
241 mov eax, ebx ; Mwait Cx, Target C-State per eax[7:4]
242 shl eax, 4
243 mwait
244 jmp MwaitLoop
245 HltLoop:
246 cli
247 hlt
248 jmp HltLoop
249 AsmRelocateApLoopEnd:
250
251 ;-------------------------------------------------------------------------------------
252 ; AsmGetAddressMap (&AddressMap);
253 ;-------------------------------------------------------------------------------------
254 global ASM_PFX(AsmGetAddressMap)
255 ASM_PFX(AsmGetAddressMap):
256 pushad
257 mov ebp,esp
258
259 mov ebx, [ebp + 24h]
260 mov dword [ebx], RendezvousFunnelProcStart
261 mov dword [ebx + 4h], Flat32Start - RendezvousFunnelProcStart
262 mov dword [ebx + 8h], RendezvousFunnelProcEnd - RendezvousFunnelProcStart
263 mov dword [ebx + 0Ch], AsmRelocateApLoopStart
264 mov dword [ebx + 10h], AsmRelocateApLoopEnd - AsmRelocateApLoopStart
265 mov dword [ebx + 14h], Flat32Start - RendezvousFunnelProcStart
266
267 popad
268 ret
269
270 ;-------------------------------------------------------------------------------------
271 ;AsmExchangeRole procedure follows. This procedure executed by current BSP, that is
272 ;about to become an AP. It switches it'stack with the current AP.
273 ;AsmExchangeRole (IN CPU_EXCHANGE_INFO *MyInfo, IN CPU_EXCHANGE_INFO *OthersInfo);
274 ;-------------------------------------------------------------------------------------
275 global ASM_PFX(AsmExchangeRole)
276 ASM_PFX(AsmExchangeRole):
277 ; DO NOT call other functions in this function, since 2 CPU may use 1 stack
278 ; at the same time. If 1 CPU try to call a function, stack will be corrupted.
279 pushad
280 mov ebp,esp
281
282 ; esi contains MyInfo pointer
283 mov esi, [ebp + 24h]
284
285 ; edi contains OthersInfo pointer
286 mov edi, [ebp + 28h]
287
288 ;Store EFLAGS, GDTR and IDTR register to stack
289 pushfd
290 mov eax, cr4
291 push eax ; push cr4 firstly
292 mov eax, cr0
293 push eax
294
295 sgdt [esi + 8]
296 sidt [esi + 14]
297
298 ; Store the its StackPointer
299 mov [esi + 4],esp
300
301 ; update its switch state to STORED
302 mov byte [esi], CPU_SWITCH_STATE_STORED
303
304 WaitForOtherStored:
305 ; wait until the other CPU finish storing its state
306 cmp byte [edi], CPU_SWITCH_STATE_STORED
307 jz OtherStored
308 pause
309 jmp WaitForOtherStored
310
311 OtherStored:
312 ; Since another CPU already stored its state, load them
313 ; load GDTR value
314 lgdt [edi + 8]
315
316 ; load IDTR value
317 lidt [edi + 14]
318
319 ; load its future StackPointer
320 mov esp, [edi + 4]
321
322 ; update the other CPU's switch state to LOADED
323 mov byte [edi], CPU_SWITCH_STATE_LOADED
324
325 WaitForOtherLoaded:
326 ; wait until the other CPU finish loading new state,
327 ; otherwise the data in stack may corrupt
328 cmp byte [esi], CPU_SWITCH_STATE_LOADED
329 jz OtherLoaded
330 pause
331 jmp WaitForOtherLoaded
332
333 OtherLoaded:
334 ; since the other CPU already get the data it want, leave this procedure
335 pop eax
336 mov cr0, eax
337 pop eax
338 mov cr4, eax
339 popfd
340
341 popad
342 ret