]> git.proxmox.com Git - mirror_edk2.git/blame - UefiCpuPkg/CpuMpPei/Ia32/MpFuncs.nasm
UefiCpuPkg/CpuMpPei: Consume MpInitLib to produce CPU MP PPI services
[mirror_edk2.git] / UefiCpuPkg / CpuMpPei / Ia32 / MpFuncs.nasm
CommitLineData
ea0f431c 1;------------------------------------------------------------------------------ ;\r
aad5ee48 2; Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>\r
ea0f431c
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
01beffa7 51 mov si, ModeOffsetLocation\r
aad5ee48
JF
52 mov eax, [si]\r
53 mov si, CodeSegmentLocation\r
54 mov edx, [si]\r
ea0f431c 55 mov di, ax\r
aad5ee48
JF
56 sub di, 02h\r
57 mov [di], dx\r
58 sub di, 04h\r
ea0f431c
JF
59 add eax, ebx\r
60 mov [di],eax\r
61\r
aad5ee48
JF
62 mov si, DataSegmentLocation\r
63 mov edx, [si]\r
64\r
ea0f431c
JF
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
74 mov eax, cr0 ;Get control register 0\r
75 or eax, 000000003h ;Set PE bit (bit #0) & MP\r
76 mov cr0, eax\r
77\r
aad5ee48 78 jmp 0:strict dword 0 ; far jump to protected mode\r
ea0f431c
JF
79BITS 32\r
80Flat32Start: ; protected mode entry point\r
aad5ee48
JF
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
ea0f431c
JF
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
98 add edi, NumApsExecutingLoction\r
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
136 call eax ; invoke C function\r
137\r
138 jmp $ ; never reach here\r
139RendezvousFunnelProcEnd:\r
140\r
ea0f431c
JF
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
01beffa7 152 mov dword [ebx + 8h], RendezvousFunnelProcEnd - RendezvousFunnelProcStart\r
ea0f431c
JF
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