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