]> git.proxmox.com Git - mirror_edk2.git/blame - UefiCpuPkg/CpuMpPei/X64/MpFuncs.nasm
BootManagerLib: Update copyright, use BSD license instead of Intel license.
[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
178global ASM_PFX(AsmCliHltLoop)\r
179ASM_PFX(AsmCliHltLoop):\r
180 cli\r
181 hlt\r
182 jmp $-2\r
183\r
184;-------------------------------------------------------------------------------------\r
185; AsmGetAddressMap (&AddressMap);\r
186;-------------------------------------------------------------------------------------\r
187global ASM_PFX(AsmGetAddressMap)\r
188ASM_PFX(AsmGetAddressMap):\r
189 mov rax, ASM_PFX(RendezvousFunnelProc)\r
190 mov qword [rcx], rax\r
191 mov qword [rcx + 8h], Flat32Start - RendezvousFunnelProcStart\r
192 mov qword [rcx + 10h], LongModeStart - RendezvousFunnelProcStart\r
193 mov qword [rcx + 18h], RendezvousFunnelProcEnd - RendezvousFunnelProcStart\r
194 ret\r
195\r
196;-------------------------------------------------------------------------------------\r
197;AsmExchangeRole procedure follows. This procedure executed by current BSP, that is\r
198;about to become an AP. It switches it'stack with the current AP.\r
199;AsmExchangeRole (IN CPU_EXCHANGE_INFO *MyInfo, IN CPU_EXCHANGE_INFO *OthersInfo);\r
200;-------------------------------------------------------------------------------------\r
201global ASM_PFX(AsmExchangeRole)\r
202ASM_PFX(AsmExchangeRole):\r
203 ; DO NOT call other functions in this function, since 2 CPU may use 1 stack\r
204 ; at the same time. If 1 CPU try to call a function, stack will be corrupted.\r
205\r
206 push rax\r
207 push rbx\r
208 push rcx\r
209 push rdx\r
210 push rsi\r
211 push rdi\r
212 push rbp\r
213 push r8\r
214 push r9\r
215 push r10\r
216 push r11\r
217 push r12\r
218 push r13\r
219 push r14\r
220 push r15\r
221\r
222 mov rax, cr0\r
223 push rax\r
224\r
225 mov rax, cr4\r
226 push rax\r
227\r
228 ; rsi contains MyInfo pointer\r
229 mov rsi, rcx\r
230\r
231 ; rdi contains OthersInfo pointer\r
232 mov rdi, rdx\r
233\r
234 ;Store EFLAGS, GDTR and IDTR regiter to stack\r
235 pushfq\r
236 sgdt [rsi + 16]\r
237 sidt [rsi + 26]\r
238\r
239 ; Store the its StackPointer\r
240 mov [rsi + 8], rsp\r
241\r
242 ; update its switch state to STORED\r
243 mov byte [rsi], CPU_SWITCH_STATE_STORED\r
244\r
245WaitForOtherStored:\r
246 ; wait until the other CPU finish storing its state\r
247 cmp byte [rdi], CPU_SWITCH_STATE_STORED\r
248 jz OtherStored\r
249 pause\r
250 jmp WaitForOtherStored\r
251\r
252OtherStored:\r
253 ; Since another CPU already stored its state, load them\r
254 ; load GDTR value\r
255 lgdt [rdi + 16]\r
256\r
257 ; load IDTR value\r
258 lidt [rdi + 26]\r
259\r
260 ; load its future StackPointer\r
261 mov rsp, [rdi + 8]\r
262\r
263 ; update the other CPU's switch state to LOADED\r
264 mov byte [rdi], CPU_SWITCH_STATE_LOADED\r
265\r
266WaitForOtherLoaded:\r
267 ; wait until the other CPU finish loading new state,\r
268 ; otherwise the data in stack may corrupt\r
269 cmp byte [rsi], CPU_SWITCH_STATE_LOADED\r
270 jz OtherLoaded\r
271 pause\r
272 jmp WaitForOtherLoaded\r
273\r
274OtherLoaded:\r
275 ; since the other CPU already get the data it want, leave this procedure\r
276 popfq\r
277\r
278 pop rax\r
279 mov cr4, rax\r
280\r
281 pop rax\r
282 mov cr0, rax\r
283\r
284 pop r15\r
285 pop r14\r
286 pop r13\r
287 pop r12\r
288 pop r11\r
289 pop r10\r
290 pop r9\r
291 pop r8\r
292 pop rbp\r
293 pop rdi\r
294 pop rsi\r
295 pop rdx\r
296 pop rcx\r
297 pop rbx\r
298 pop rax\r
299\r
300 ret\r
301\r
302global ASM_PFX(AsmInitializeGdt)\r
303ASM_PFX(AsmInitializeGdt):\r
304 push rbp\r
305 mov rbp, rsp\r
306\r
307 lgdt [rcx] ; update the GDTR\r
308\r
309 sub rsp, 0x10\r
310 mov rax, ASM_PFX(SetCodeSelectorFarJump)\r
311 mov [rsp], rax\r
312 mov rdx, LONG_MODE_CS\r
313 mov [rsp + 4], dx ; get new CS\r
314 jmp far dword [rsp] ; far jump with new CS\r
315ASM_PFX(SetCodeSelectorFarJump):\r
316 add rsp, 0x10\r
317\r
318 mov rax, LONG_MODE_DS ; get new DS\r
319 mov ds, ax\r
320 mov es, ax\r
321 mov fs, ax\r
322 mov gs, ax\r
323 mov ss, ax\r
324\r
325 pop rbp\r
326\r
327 ret\r