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