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