]> git.proxmox.com Git - mirror_edk2.git/blob - UefiCpuPkg/Library/MpInitLib/Ia32/MpFuncs.nasm
UefiCpuPkg/MpInitLib: Program AP stack in fixed address
[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 jnb X2Apic
158 ; Processor is not x2APIC capable, so get 8-bit APIC ID
159 mov eax, 1
160 cpuid
161 shr ebx, 24
162 mov edx, ebx
163 jmp GetProcessorNumber
164
165 X2Apic:
166 ; Processor is x2APIC capable, so get 32-bit x2APIC ID
167 mov eax, 0bh
168 xor ecx, ecx
169 cpuid
170 ; edx save x2APIC ID
171
172 GetProcessorNumber:
173 ;
174 ; Get processor number for this AP
175 ; Note that BSP may become an AP due to SwitchBsp()
176 ;
177 xor ebx, ebx
178 lea eax, [esi + CpuInfoLocation]
179 mov edi, [eax]
180
181 GetNextProcNumber:
182 cmp [edi], edx ; APIC ID match?
183 jz ProgramStack
184 add edi, 16
185 inc ebx
186 jmp GetNextProcNumber
187
188 ProgramStack:
189 mov esp, [edi + 12]
190
191 CProcedureInvoke:
192 push ebp ; push BIST data at top of AP stack
193 xor ebp, ebp ; clear ebp for call stack trace
194 push ebp
195 mov ebp, esp
196
197 mov eax, ASM_PFX(InitializeFloatingPointUnits)
198 call eax ; Call assembly function to initialize FPU per UEFI spec
199
200 push ebx ; Push NumApsExecuting
201 mov eax, esi
202 add eax, LockLocation
203 push eax ; push address of exchange info data buffer
204
205 mov edi, esi
206 add edi, ApProcedureLocation
207 mov eax, [edi]
208
209 call eax ; Invoke C function
210
211 jmp $ ; Never reach here
212 RendezvousFunnelProcEnd:
213
214 ;-------------------------------------------------------------------------------------
215 ; AsmRelocateApLoop (MwaitSupport, ApTargetCState, PmCodeSegment);
216 ;-------------------------------------------------------------------------------------
217 global ASM_PFX(AsmRelocateApLoop)
218 ASM_PFX(AsmRelocateApLoop):
219 AsmRelocateApLoopStart:
220 cmp byte [esp + 4], 1
221 jnz HltLoop
222 MwaitLoop:
223 mov eax, esp
224 xor ecx, ecx
225 xor edx, edx
226 monitor
227 mov eax, [esp + 8] ; Mwait Cx, Target C-State per eax[7:4]
228 shl eax, 4
229 mwait
230 jmp MwaitLoop
231 HltLoop:
232 cli
233 hlt
234 jmp HltLoop
235 ret
236 AsmRelocateApLoopEnd:
237
238 ;-------------------------------------------------------------------------------------
239 ; AsmGetAddressMap (&AddressMap);
240 ;-------------------------------------------------------------------------------------
241 global ASM_PFX(AsmGetAddressMap)
242 ASM_PFX(AsmGetAddressMap):
243 pushad
244 mov ebp,esp
245
246 mov ebx, [ebp + 24h]
247 mov dword [ebx], RendezvousFunnelProcStart
248 mov dword [ebx + 4h], Flat32Start - RendezvousFunnelProcStart
249 mov dword [ebx + 8h], RendezvousFunnelProcEnd - RendezvousFunnelProcStart
250 mov dword [ebx + 0Ch], AsmRelocateApLoopStart
251 mov dword [ebx + 10h], AsmRelocateApLoopEnd - AsmRelocateApLoopStart
252
253 popad
254 ret
255
256 ;-------------------------------------------------------------------------------------
257 ;AsmExchangeRole procedure follows. This procedure executed by current BSP, that is
258 ;about to become an AP. It switches it'stack with the current AP.
259 ;AsmExchangeRole (IN CPU_EXCHANGE_INFO *MyInfo, IN CPU_EXCHANGE_INFO *OthersInfo);
260 ;-------------------------------------------------------------------------------------
261 global ASM_PFX(AsmExchangeRole)
262 ASM_PFX(AsmExchangeRole):
263 ; DO NOT call other functions in this function, since 2 CPU may use 1 stack
264 ; at the same time. If 1 CPU try to call a function, stack will be corrupted.
265 pushad
266 mov ebp,esp
267
268 ; esi contains MyInfo pointer
269 mov esi, [ebp + 24h]
270
271 ; edi contains OthersInfo pointer
272 mov edi, [ebp + 28h]
273
274 ;Store EFLAGS, GDTR and IDTR register to stack
275 pushfd
276 mov eax, cr4
277 push eax ; push cr4 firstly
278 mov eax, cr0
279 push eax
280
281 sgdt [esi + 8]
282 sidt [esi + 14]
283
284 ; Store the its StackPointer
285 mov [esi + 4],esp
286
287 ; update its switch state to STORED
288 mov byte [esi], CPU_SWITCH_STATE_STORED
289
290 WaitForOtherStored:
291 ; wait until the other CPU finish storing its state
292 cmp byte [edi], CPU_SWITCH_STATE_STORED
293 jz OtherStored
294 pause
295 jmp WaitForOtherStored
296
297 OtherStored:
298 ; Since another CPU already stored its state, load them
299 ; load GDTR value
300 lgdt [edi + 8]
301
302 ; load IDTR value
303 lidt [edi + 14]
304
305 ; load its future StackPointer
306 mov esp, [edi + 4]
307
308 ; update the other CPU's switch state to LOADED
309 mov byte [edi], CPU_SWITCH_STATE_LOADED
310
311 WaitForOtherLoaded:
312 ; wait until the other CPU finish loading new state,
313 ; otherwise the data in stack may corrupt
314 cmp byte [esi], CPU_SWITCH_STATE_LOADED
315 jz OtherLoaded
316 pause
317 jmp WaitForOtherLoaded
318
319 OtherLoaded:
320 ; since the other CPU already get the data it want, leave this procedure
321 pop eax
322 mov cr0, eax
323 pop eax
324 mov cr4, eax
325 popfd
326
327 popad
328 ret