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