]> git.proxmox.com Git - mirror_edk2.git/blob - UefiCpuPkg/Library/MpInitLib/Ia32/MpFuncs.nasm
UefiCpuPkg/MpInitLib: split wake up buffer into two parts
[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, 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 mov eax, esp
243 xor ecx, ecx
244 xor edx, edx
245 monitor
246 mov eax, ebx ; Mwait Cx, Target C-State per eax[7:4]
247 shl eax, 4
248 mwait
249 jmp MwaitLoop
250 HltLoop:
251 cli
252 hlt
253 jmp HltLoop
254 AsmRelocateApLoopEnd:
255
256 ;-------------------------------------------------------------------------------------
257 ; AsmGetAddressMap (&AddressMap);
258 ;-------------------------------------------------------------------------------------
259 global ASM_PFX(AsmGetAddressMap)
260 ASM_PFX(AsmGetAddressMap):
261 pushad
262 mov ebp,esp
263
264 mov ebx, [ebp + 24h]
265 mov dword [ebx], RendezvousFunnelProcStart
266 mov dword [ebx + 4h], Flat32Start - RendezvousFunnelProcStart
267 mov dword [ebx + 8h], RendezvousFunnelProcEnd - RendezvousFunnelProcStart
268 mov dword [ebx + 0Ch], AsmRelocateApLoopStart
269 mov dword [ebx + 10h], AsmRelocateApLoopEnd - AsmRelocateApLoopStart
270 mov dword [ebx + 14h], Flat32Start - RendezvousFunnelProcStart
271
272 popad
273 ret
274
275 ;-------------------------------------------------------------------------------------
276 ;AsmExchangeRole procedure follows. This procedure executed by current BSP, that is
277 ;about to become an AP. It switches it'stack with the current AP.
278 ;AsmExchangeRole (IN CPU_EXCHANGE_INFO *MyInfo, IN CPU_EXCHANGE_INFO *OthersInfo);
279 ;-------------------------------------------------------------------------------------
280 global ASM_PFX(AsmExchangeRole)
281 ASM_PFX(AsmExchangeRole):
282 ; DO NOT call other functions in this function, since 2 CPU may use 1 stack
283 ; at the same time. If 1 CPU try to call a function, stack will be corrupted.
284 pushad
285 mov ebp,esp
286
287 ; esi contains MyInfo pointer
288 mov esi, [ebp + 24h]
289
290 ; edi contains OthersInfo pointer
291 mov edi, [ebp + 28h]
292
293 ;Store EFLAGS, GDTR and IDTR register to stack
294 pushfd
295 mov eax, cr4
296 push eax ; push cr4 firstly
297 mov eax, cr0
298 push eax
299
300 sgdt [esi + 8]
301 sidt [esi + 14]
302
303 ; Store the its StackPointer
304 mov [esi + 4],esp
305
306 ; update its switch state to STORED
307 mov byte [esi], CPU_SWITCH_STATE_STORED
308
309 WaitForOtherStored:
310 ; wait until the other CPU finish storing its state
311 cmp byte [edi], CPU_SWITCH_STATE_STORED
312 jz OtherStored
313 pause
314 jmp WaitForOtherStored
315
316 OtherStored:
317 ; Since another CPU already stored its state, load them
318 ; load GDTR value
319 lgdt [edi + 8]
320
321 ; load IDTR value
322 lidt [edi + 14]
323
324 ; load its future StackPointer
325 mov esp, [edi + 4]
326
327 ; update the other CPU's switch state to LOADED
328 mov byte [edi], CPU_SWITCH_STATE_LOADED
329
330 WaitForOtherLoaded:
331 ; wait until the other CPU finish loading new state,
332 ; otherwise the data in stack may corrupt
333 cmp byte [esi], CPU_SWITCH_STATE_LOADED
334 jz OtherLoaded
335 pause
336 jmp WaitForOtherLoaded
337
338 OtherLoaded:
339 ; since the other CPU already get the data it want, leave this procedure
340 pop eax
341 mov cr0, eax
342 pop eax
343 mov cr4, eax
344 popfd
345
346 popad
347 ret