]> git.proxmox.com Git - mirror_edk2.git/blame - UefiCpuPkg/Library/MpInitLib/Ia32/MpFuncs.nasm
UefiCpuPkg/MpInitLib: Fix typo and clean up the code
[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
88 mov edi, esi\r
89 add edi, LockLocation\r
90 mov eax, NotVacantFlag\r
91\r
92TestLock:\r
93 xchg [edi], eax\r
94 cmp eax, NotVacantFlag\r
95 jz TestLock\r
96\r
97 mov edi, esi\r
8396e2dd 98 add edi, NumApsExecutingLocation\r
d94e5f67
JF
99 inc dword [edi]\r
100 mov ebx, [edi]\r
101\r
102ProgramStack:\r
103 mov edi, esi\r
104 add edi, StackSizeLocation\r
105 mov eax, [edi]\r
106 mov edi, esi\r
107 add edi, StackStartAddressLocation\r
108 add eax, [edi]\r
109 mov esp, eax\r
110 mov [edi], eax\r
111\r
112Releaselock:\r
113 mov eax, VacantFlag\r
114 mov edi, esi\r
115 add edi, LockLocation\r
116 xchg [edi], eax\r
117\r
118CProcedureInvoke:\r
119 push ebp ; push BIST data at top of AP stack\r
120 xor ebp, ebp ; clear ebp for call stack trace\r
121 push ebp\r
122 mov ebp, esp\r
123\r
124 mov eax, ASM_PFX(InitializeFloatingPointUnits)\r
125 call eax ; Call assembly function to initialize FPU per UEFI spec\r
126\r
127 push ebx ; Push NumApsExecuting\r
128 mov eax, esi\r
129 add eax, LockLocation\r
130 push eax ; push address of exchange info data buffer\r
131\r
132 mov edi, esi\r
133 add edi, ApProcedureLocation\r
134 mov eax, [edi]\r
135\r
8396e2dd 136 call eax ; Invoke C function\r
d94e5f67 137\r
8396e2dd 138 jmp $ ; Never reach here\r
d94e5f67
JF
139RendezvousFunnelProcEnd:\r
140\r
141;-------------------------------------------------------------------------------------\r
142; AsmGetAddressMap (&AddressMap);\r
143;-------------------------------------------------------------------------------------\r
144global ASM_PFX(AsmGetAddressMap)\r
145ASM_PFX(AsmGetAddressMap):\r
146 pushad\r
147 mov ebp,esp\r
148\r
149 mov ebx, [ebp + 24h]\r
150 mov dword [ebx], RendezvousFunnelProcStart\r
151 mov dword [ebx + 4h], Flat32Start - RendezvousFunnelProcStart\r
152 mov dword [ebx + 8h], RendezvousFunnelProcEnd - RendezvousFunnelProcStart\r
153\r
154 popad\r
155 ret\r
156\r
157;-------------------------------------------------------------------------------------\r
158;AsmExchangeRole procedure follows. This procedure executed by current BSP, that is\r
159;about to become an AP. It switches it'stack with the current AP.\r
160;AsmExchangeRole (IN CPU_EXCHANGE_INFO *MyInfo, IN CPU_EXCHANGE_INFO *OthersInfo);\r
161;-------------------------------------------------------------------------------------\r
162global ASM_PFX(AsmExchangeRole)\r
163ASM_PFX(AsmExchangeRole):\r
164 ; DO NOT call other functions in this function, since 2 CPU may use 1 stack\r
165 ; at the same time. If 1 CPU try to call a function, stack will be corrupted.\r
166 pushad\r
167 mov ebp,esp\r
168\r
169 ; esi contains MyInfo pointer\r
170 mov esi, [ebp + 24h]\r
171\r
172 ; edi contains OthersInfo pointer\r
173 mov edi, [ebp + 28h]\r
174\r
175 ;Store EFLAGS, GDTR and IDTR register to stack\r
176 pushfd\r
177 mov eax, cr4\r
178 push eax ; push cr4 firstly\r
179 mov eax, cr0\r
180 push eax\r
181\r
182 sgdt [esi + 8]\r
183 sidt [esi + 14]\r
184\r
185 ; Store the its StackPointer\r
186 mov [esi + 4],esp\r
187\r
188 ; update its switch state to STORED\r
189 mov byte [esi], CPU_SWITCH_STATE_STORED\r
190\r
191WaitForOtherStored:\r
192 ; wait until the other CPU finish storing its state\r
193 cmp byte [edi], CPU_SWITCH_STATE_STORED\r
194 jz OtherStored\r
195 pause\r
196 jmp WaitForOtherStored\r
197\r
198OtherStored:\r
199 ; Since another CPU already stored its state, load them\r
200 ; load GDTR value\r
201 lgdt [edi + 8]\r
202\r
203 ; load IDTR value\r
204 lidt [edi + 14]\r
205\r
206 ; load its future StackPointer\r
207 mov esp, [edi + 4]\r
208\r
209 ; update the other CPU's switch state to LOADED\r
210 mov byte [edi], CPU_SWITCH_STATE_LOADED\r
211\r
212WaitForOtherLoaded:\r
213 ; wait until the other CPU finish loading new state,\r
214 ; otherwise the data in stack may corrupt\r
215 cmp byte [esi], CPU_SWITCH_STATE_LOADED\r
216 jz OtherLoaded\r
217 pause\r
218 jmp WaitForOtherLoaded\r
219\r
220OtherLoaded:\r
221 ; since the other CPU already get the data it want, leave this procedure\r
222 pop eax\r
223 mov cr0, eax\r
224 pop eax\r
225 mov cr4, eax\r
226 popfd\r
227\r
228 popad\r
229 ret\r