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