]> git.proxmox.com Git - mirror_edk2.git/blame - UefiCpuPkg/CpuMpPei/X64/MpFuncs.nasm
UefiCpuPkg/CpuMpPei/Ia32: Use CodeSegment and DataSegment fields
[mirror_edk2.git] / UefiCpuPkg / CpuMpPei / X64 / 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
24DEFAULT REL\r
25\r
26SECTION .text\r
27\r
28;-------------------------------------------------------------------------------------\r
29;RendezvousFunnelProc procedure follows. All APs execute their procedure. This\r
30;procedure serializes all the AP processors through an Init sequence. It must be\r
31;noted that APs arrive here very raw...ie: real mode, no stack.\r
32;ALSO THIS PROCEDURE IS EXECUTED BY APs ONLY ON 16 BIT MODE. HENCE THIS PROC\r
33;IS IN MACHINE CODE.\r
34;-------------------------------------------------------------------------------------\r
35global ASM_PFX(RendezvousFunnelProc)\r
36ASM_PFX(RendezvousFunnelProc):\r
37RendezvousFunnelProcStart:\r
38; At this point CS = 0x(vv00) and ip= 0x0.\r
39; Save BIST information to ebp firstly\r
40BITS 16\r
41\r
42 mov eax, 1234h\r
43 mov ebp, eax ; save BIST information\r
44\r
45 mov ax, cs\r
46 mov ds, ax\r
47 mov es, ax\r
48 mov ss, ax\r
49 xor ax, ax\r
50 mov fs, ax\r
51 mov gs, ax\r
52\r
53 mov si, BufferStartLocation\r
54 mov ebx, [si]\r
55\r
56 mov di, PmodeOffsetLocation\r
57 mov eax, [di]\r
58 mov di, ax\r
59 sub di, 06h\r
60 add eax, ebx\r
61 mov [di],eax\r
62\r
63 mov di, LmodeOffsetLocation\r
64 mov eax, [di]\r
65 mov di, ax\r
66 sub di, 06h\r
67 add eax, ebx\r
68 mov [di],eax\r
69\r
70\r
71 mov si, Cr3Location\r
72 mov ecx,[si] ; ECX is keeping the value of CR3\r
73\r
74 mov si, GdtrLocation\r
75o32 lgdt [cs:si]\r
76\r
77 mov si, IdtrLocation\r
78o32 lidt [cs:si]\r
79\r
80\r
81 xor ax, ax\r
82 mov ds, ax\r
83\r
84 mov eax, cr0 ;Get control register 0\r
85 or eax, 000000003h ;Set PE bit (bit #0) & MP\r
86 mov cr0, eax\r
87\r
88 jmp PROTECT_MODE_CS:strict dword 0 ; far jump to protected mode\r
89BITS 32\r
90Flat32Start: ; protected mode entry point\r
91 mov ax, PROTECT_MODE_DS\r
92 mov ds, ax\r
93 mov es, ax\r
94 mov fs, ax\r
95 mov gs, ax\r
96 mov ss, ax\r
97\r
98 mov eax, cr4\r
99 bts eax, 5\r
100 mov cr4, eax\r
101\r
102 mov cr3, ecx\r
103\r
104\r
105 mov ecx, 0c0000080h ; EFER MSR number.\r
106 rdmsr ; Read EFER.\r
107 bts eax, 8 ; Set LME=1.\r
108 wrmsr ; Write EFER.\r
109\r
110 mov eax, cr0 ; Read CR0.\r
111 bts eax, 31 ; Set PG=1.\r
112 mov cr0, eax ; Write CR0.\r
113\r
114 jmp LONG_MODE_CS:strict dword 0 ; far jump to long mode\r
115BITS 64\r
116LongModeStart:\r
117 mov ax, LONG_MODE_DS\r
118 mov ds, ax\r
119 mov es, ax\r
120 mov ss, ax\r
121\r
122 mov esi, ebx\r
123 mov edi, esi\r
124 add edi, LockLocation\r
125 mov rax, NotVacantFlag\r
126\r
127TestLock:\r
128 xchg qword [edi], rax\r
129 cmp rax, NotVacantFlag\r
130 jz TestLock\r
131\r
132 mov edi, esi\r
133 add edi, NumApsExecutingLoction\r
134 inc dword [edi]\r
135 mov ebx, [edi]\r
136\r
137ProgramStack:\r
138 mov edi, esi\r
139 add edi, StackSizeLocation\r
140 mov rax, qword [edi]\r
141 mov edi, esi\r
142 add edi, StackStartAddressLocation\r
143 add rax, qword [edi]\r
144 mov rsp, rax\r
145 mov qword [edi], rax\r
146\r
147Releaselock:\r
148 mov rax, VacantFlag\r
149 mov edi, esi\r
150 add edi, LockLocation\r
151 xchg qword [edi], rax\r
152\r
153CProcedureInvoke:\r
154 push rbp ; push BIST data at top of AP stack\r
155 xor rbp, rbp ; clear ebp for call stack trace\r
156 push rbp\r
157 mov rbp, rsp\r
158\r
159 mov rax, ASM_PFX(InitializeFloatingPointUnits)\r
160 sub rsp, 20h\r
161 call rax ; Call assembly function to initialize FPU per UEFI spec\r
162 add rsp, 20h\r
163\r
164 mov edx, ebx ; edx is NumApsExecuting\r
165 mov ecx, esi\r
166 add ecx, LockLocation ; rcx is address of exchange info data buffer\r
167\r
168 mov edi, esi\r
169 add edi, ApProcedureLocation\r
170 mov rax, qword [edi]\r
171\r
172 sub rsp, 20h\r
173 call rax ; invoke C function\r
174 add rsp, 20h\r
175\r
176RendezvousFunnelProcEnd:\r
177\r
ea0f431c
JF
178;-------------------------------------------------------------------------------------\r
179; AsmGetAddressMap (&AddressMap);\r
180;-------------------------------------------------------------------------------------\r
181global ASM_PFX(AsmGetAddressMap)\r
182ASM_PFX(AsmGetAddressMap):\r
183 mov rax, ASM_PFX(RendezvousFunnelProc)\r
184 mov qword [rcx], rax\r
185 mov qword [rcx + 8h], Flat32Start - RendezvousFunnelProcStart\r
186 mov qword [rcx + 10h], LongModeStart - RendezvousFunnelProcStart\r
187 mov qword [rcx + 18h], RendezvousFunnelProcEnd - RendezvousFunnelProcStart\r
188 ret\r
189\r
190;-------------------------------------------------------------------------------------\r
191;AsmExchangeRole procedure follows. This procedure executed by current BSP, that is\r
192;about to become an AP. It switches it'stack with the current AP.\r
193;AsmExchangeRole (IN CPU_EXCHANGE_INFO *MyInfo, IN CPU_EXCHANGE_INFO *OthersInfo);\r
194;-------------------------------------------------------------------------------------\r
195global ASM_PFX(AsmExchangeRole)\r
196ASM_PFX(AsmExchangeRole):\r
197 ; DO NOT call other functions in this function, since 2 CPU may use 1 stack\r
198 ; at the same time. If 1 CPU try to call a function, stack will be corrupted.\r
199\r
200 push rax\r
201 push rbx\r
202 push rcx\r
203 push rdx\r
204 push rsi\r
205 push rdi\r
206 push rbp\r
207 push r8\r
208 push r9\r
209 push r10\r
210 push r11\r
211 push r12\r
212 push r13\r
213 push r14\r
214 push r15\r
215\r
216 mov rax, cr0\r
217 push rax\r
218\r
219 mov rax, cr4\r
220 push rax\r
221\r
222 ; rsi contains MyInfo pointer\r
223 mov rsi, rcx\r
224\r
225 ; rdi contains OthersInfo pointer\r
226 mov rdi, rdx\r
227\r
228 ;Store EFLAGS, GDTR and IDTR regiter to stack\r
229 pushfq\r
230 sgdt [rsi + 16]\r
231 sidt [rsi + 26]\r
232\r
233 ; Store the its StackPointer\r
234 mov [rsi + 8], rsp\r
235\r
236 ; update its switch state to STORED\r
237 mov byte [rsi], CPU_SWITCH_STATE_STORED\r
238\r
239WaitForOtherStored:\r
240 ; wait until the other CPU finish storing its state\r
241 cmp byte [rdi], CPU_SWITCH_STATE_STORED\r
242 jz OtherStored\r
243 pause\r
244 jmp WaitForOtherStored\r
245\r
246OtherStored:\r
247 ; Since another CPU already stored its state, load them\r
248 ; load GDTR value\r
249 lgdt [rdi + 16]\r
250\r
251 ; load IDTR value\r
252 lidt [rdi + 26]\r
253\r
254 ; load its future StackPointer\r
255 mov rsp, [rdi + 8]\r
256\r
257 ; update the other CPU's switch state to LOADED\r
258 mov byte [rdi], CPU_SWITCH_STATE_LOADED\r
259\r
260WaitForOtherLoaded:\r
261 ; wait until the other CPU finish loading new state,\r
262 ; otherwise the data in stack may corrupt\r
263 cmp byte [rsi], CPU_SWITCH_STATE_LOADED\r
264 jz OtherLoaded\r
265 pause\r
266 jmp WaitForOtherLoaded\r
267\r
268OtherLoaded:\r
269 ; since the other CPU already get the data it want, leave this procedure\r
270 popfq\r
271\r
272 pop rax\r
273 mov cr4, rax\r
274\r
275 pop rax\r
276 mov cr0, rax\r
277\r
278 pop r15\r
279 pop r14\r
280 pop r13\r
281 pop r12\r
282 pop r11\r
283 pop r10\r
284 pop r9\r
285 pop r8\r
286 pop rbp\r
287 pop rdi\r
288 pop rsi\r
289 pop rdx\r
290 pop rcx\r
291 pop rbx\r
292 pop rax\r
293\r
294 ret\r
295\r
296global ASM_PFX(AsmInitializeGdt)\r
297ASM_PFX(AsmInitializeGdt):\r
298 push rbp\r
299 mov rbp, rsp\r
300\r
301 lgdt [rcx] ; update the GDTR\r
302\r
303 sub rsp, 0x10\r
304 mov rax, ASM_PFX(SetCodeSelectorFarJump)\r
305 mov [rsp], rax\r
306 mov rdx, LONG_MODE_CS\r
307 mov [rsp + 4], dx ; get new CS\r
308 jmp far dword [rsp] ; far jump with new CS\r
309ASM_PFX(SetCodeSelectorFarJump):\r
310 add rsp, 0x10\r
311\r
312 mov rax, LONG_MODE_DS ; get new DS\r
313 mov ds, ax\r
314 mov es, ax\r
315 mov fs, ax\r
316 mov gs, ax\r
317 mov ss, ax\r
318\r
319 pop rbp\r
320\r
321 ret\r