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