]> git.proxmox.com Git - mirror_edk2.git/blame - UefiCpuPkg/CpuMpPei/Ia32/MpFuncs.nasm
UefiCpuPkg/CpuMpPei: Load microcode if found newer revision
[mirror_edk2.git] / UefiCpuPkg / CpuMpPei / Ia32 / MpFuncs.nasm
CommitLineData
ea0f431c
JF
1;------------------------------------------------------------------------------ ;\r
2; Copyright (c) 2015, 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 di, PmodeOffsetLocation\r
52 mov eax, [di]\r
53 mov di, ax\r
54 sub di, 06h\r
55 add eax, ebx\r
56 mov [di],eax\r
57\r
58 mov si, GdtrLocation\r
59o32 lgdt [cs:si]\r
60\r
61 mov si, IdtrLocation\r
62o32 lidt [cs:si]\r
63\r
64 xor ax, ax\r
65 mov ds, ax\r
66\r
67 mov eax, cr0 ;Get control register 0\r
68 or eax, 000000003h ;Set PE bit (bit #0) & MP\r
69 mov cr0, eax\r
70\r
71 jmp PROTECT_MODE_CS:strict dword 0 ; far jump to protected mode\r
72BITS 32\r
73Flat32Start: ; protected mode entry point\r
74 mov ax, PROTECT_MODE_DS\r
75 mov ds, ax\r
76 mov es, ax\r
77 mov fs, ax\r
78 mov gs, ax\r
79 mov ss, ax\r
80\r
81 mov esi, ebx\r
82 mov edi, esi\r
83 add edi, LockLocation\r
84 mov eax, NotVacantFlag\r
85\r
86TestLock:\r
87 xchg [edi], eax\r
88 cmp eax, NotVacantFlag\r
89 jz TestLock\r
90\r
91 mov edi, esi\r
92 add edi, NumApsExecutingLoction\r
93 inc dword [edi]\r
94 mov ebx, [edi]\r
95\r
96ProgramStack:\r
97 mov edi, esi\r
98 add edi, StackSizeLocation\r
99 mov eax, [edi]\r
100 mov edi, esi\r
101 add edi, StackStartAddressLocation\r
102 add eax, [edi]\r
103 mov esp, eax\r
104 mov [edi], eax\r
105\r
106Releaselock:\r
107 mov eax, VacantFlag\r
108 mov edi, esi\r
109 add edi, LockLocation\r
110 xchg [edi], eax\r
111\r
112CProcedureInvoke:\r
113 push ebp ; push BIST data at top of AP stack\r
114 xor ebp, ebp ; clear ebp for call stack trace\r
115 push ebp\r
116 mov ebp, esp\r
117\r
118 mov eax, ASM_PFX(InitializeFloatingPointUnits)\r
119 call eax ; Call assembly function to initialize FPU per UEFI spec\r
120\r
121 push ebx ; Push NumApsExecuting\r
122 mov eax, esi\r
123 add eax, LockLocation\r
124 push eax ; push address of exchange info data buffer\r
125\r
126 mov edi, esi\r
127 add edi, ApProcedureLocation\r
128 mov eax, [edi]\r
129\r
130 call eax ; invoke C function\r
131\r
132 jmp $ ; never reach here\r
133RendezvousFunnelProcEnd:\r
134\r
ea0f431c
JF
135;-------------------------------------------------------------------------------------\r
136; AsmGetAddressMap (&AddressMap);\r
137;-------------------------------------------------------------------------------------\r
138global ASM_PFX(AsmGetAddressMap)\r
139ASM_PFX(AsmGetAddressMap):\r
140 pushad\r
141 mov ebp,esp\r
142\r
143 mov ebx, [ebp + 24h]\r
144 mov dword [ebx], RendezvousFunnelProcStart\r
145 mov dword [ebx + 4h], Flat32Start - RendezvousFunnelProcStart\r
146 mov dword [ebx + 8h], 0\r
147 mov dword [ebx + 0ch], RendezvousFunnelProcEnd - RendezvousFunnelProcStart\r
148\r
149 popad\r
150 ret\r
151\r
152;-------------------------------------------------------------------------------------\r
153;AsmExchangeRole procedure follows. This procedure executed by current BSP, that is\r
154;about to become an AP. It switches it'stack with the current AP.\r
155;AsmExchangeRole (IN CPU_EXCHANGE_INFO *MyInfo, IN CPU_EXCHANGE_INFO *OthersInfo);\r
156;-------------------------------------------------------------------------------------\r
157global ASM_PFX(AsmExchangeRole)\r
158ASM_PFX(AsmExchangeRole):\r
159 ; DO NOT call other functions in this function, since 2 CPU may use 1 stack\r
160 ; at the same time. If 1 CPU try to call a function, stack will be corrupted.\r
161 pushad\r
162 mov ebp,esp\r
163\r
164 ; esi contains MyInfo pointer\r
165 mov esi, [ebp + 24h]\r
166\r
167 ; edi contains OthersInfo pointer\r
168 mov edi, [ebp + 28h]\r
169\r
170 ;Store EFLAGS, GDTR and IDTR register to stack\r
171 pushfd\r
172 mov eax, cr4\r
173 push eax ; push cr4 firstly\r
174 mov eax, cr0\r
175 push eax\r
176\r
177 sgdt [esi + 8]\r
178 sidt [esi + 14]\r
179\r
180 ; Store the its StackPointer\r
181 mov [esi + 4],esp\r
182\r
183 ; update its switch state to STORED\r
184 mov byte [esi], CPU_SWITCH_STATE_STORED\r
185\r
186WaitForOtherStored:\r
187 ; wait until the other CPU finish storing its state\r
188 cmp byte [edi], CPU_SWITCH_STATE_STORED\r
189 jz OtherStored\r
190 pause\r
191 jmp WaitForOtherStored\r
192\r
193OtherStored:\r
194 ; Since another CPU already stored its state, load them\r
195 ; load GDTR value\r
196 lgdt [edi + 8]\r
197\r
198 ; load IDTR value\r
199 lidt [edi + 14]\r
200\r
201 ; load its future StackPointer\r
202 mov esp, [edi + 4]\r
203\r
204 ; update the other CPU's switch state to LOADED\r
205 mov byte [edi], CPU_SWITCH_STATE_LOADED\r
206\r
207WaitForOtherLoaded:\r
208 ; wait until the other CPU finish loading new state,\r
209 ; otherwise the data in stack may corrupt\r
210 cmp byte [esi], CPU_SWITCH_STATE_LOADED\r
211 jz OtherLoaded\r
212 pause\r
213 jmp WaitForOtherLoaded\r
214\r
215OtherLoaded:\r
216 ; since the other CPU already get the data it want, leave this procedure\r
217 pop eax\r
218 mov cr0, eax\r
219 pop eax\r
220 mov cr4, eax\r
221 popfd\r
222\r
223 popad\r
224 ret\r
225\r
226global ASM_PFX(AsmInitializeGdt)\r
227ASM_PFX(AsmInitializeGdt):\r
228 push ebp\r
229 mov ebp, esp\r
230 pushad\r
231 mov edi, [ebp + 8] ; Load GDT register\r
232\r
233 lgdt [edi] ; and update the GDTR\r
234\r
235 push PROTECT_MODE_CS\r
236 mov eax, ASM_PFX(SetCodeSelectorFarJump)\r
237 push eax\r
238 retf\r
239ASM_PFX(SetCodeSelectorFarJump):\r
240 mov ax, PROTECT_MODE_DS ; Update the Base for the new selectors, too\r
241 mov ds, ax\r
242 mov es, ax\r
243 mov fs, ax\r
244 mov gs, ax\r
245 mov ss, ax\r
246\r
247 popad\r
248 pop ebp\r
249 ret\r