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