]> git.proxmox.com Git - mirror_edk2.git/blame - UefiCpuPkg/CpuMpPei/X64/MpFuncs.asm
UefiCpuPkg/CpuMpPei: Remove PmodeOffset and LmodeOffset
[mirror_edk2.git] / UefiCpuPkg / CpuMpPei / X64 / MpFuncs.asm
CommitLineData
ea0f431c 1;------------------------------------------------------------------------------ ;\r
d1471c01 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; 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
d1471c01
JF
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
ea0f431c
JF
45\r
46 db 0BEh ; opcode of mov si, mem16\r
47 dw BufferStartLocation ; mov si, BufferStartLocation\r
d1471c01
JF
48 db 66h, 8Bh, 1Ch ; mov ebx, dword ptr [si]\r
49\r
50 db 0BFh ; opcode of mov di, mem16 \r
01beffa7 51 dw ModeOffsetLocation ; mov di, ModeOffsetLocation\r
d1471c01
JF
52 db 66h, 8Bh, 05h ; mov eax, [di]\r
53 db 0BFh ; opcode of mov di, mem16 \r
54 dw CodeSegmentLocation ; mov di, CodeSegmentLocation\r
55 db 66h, 8Bh, 15h ; mov edx, [di]\r
56 db 89h, 0C7h ; mov di, ax\r
57 db 83h, 0EFh, 02h ; sub di, 02h \r
58 db 89h, 15h ; mov [di], dx ; Patch long mode CS\r
59 db 83h, 0EFh, 04h ; sub di, 04h\r
60 db 66h, 01h, 0D8h ; add eax, ebx\r
61 db 66h, 89h, 05h ; mov [di], eax ; Patch address\r
ea0f431c
JF
62\r
63 db 0BEh ; opcode of mov si, mem16\r
64 dw GdtrLocation ; mov si, GdtrLocation\r
65 db 66h ; db 66h\r
66 db 2Eh, 0Fh, 01h, 14h ; lgdt fword ptr cs:[si]\r
67\r
68 db 0BEh\r
69 dw IdtrLocation ; mov si, IdtrLocation\r
70 db 66h ; db 66h\r
71 db 2Eh,0Fh, 01h, 1Ch ; lidt fword ptr cs:[si]\r
72\r
d1471c01
JF
73 db 0BFh ; opcode of mov di, mem16 \r
74 dw DataSegmentLocation ; mov di, DataSegmentLocation\r
75 db 66h, 8Bh, 3Dh ; mov edi, [di] ; Save long mode DS in edi\r
ea0f431c 76\r
d1471c01
JF
77 db 0BEh\r
78 dw Cr3Location ; mov si, Cr3Location\r
79 db 66h, 8Bh, 0Ch ; mov ecx, dword ptr [si] ; ECX is keeping the value of CR3\r
ea0f431c 80\r
d1471c01
JF
81 db 31h, 0C0h ; xor ax, ax\r
82 db 8Eh, 0D8h ; mov ds, ax ; Clear data segment\r
ea0f431c 83\r
d1471c01
JF
84 db 0Fh, 20h, 0C0h ; mov eax, cr0 ; Get control register 0\r
85 db 66h, 83h, 0C8h, 03h ; or eax, 000000003h ; Set PE bit (bit #0) & MP\r
86 db 0Fh, 22h, 0C0h ; mov cr0, eax\r
ea0f431c 87\r
d1471c01
JF
88 db 0Fh, 20h, 0E0h ; mov eax, cr4\r
89 db 66h, 0Fh, 0BAh, 0E8h, 05h ; bts eax, 5\r
90 db 0Fh, 22h, 0E0h ; mov cr4, eax\r
ea0f431c
JF
91\r
92 db 0Fh, 22h, 0D9h ; mov cr3, ecx\r
93\r
d1471c01 94 db 66h, 0B9h\r
ea0f431c
JF
95 dd 0C0000080h ; mov ecx, 0c0000080h ; EFER MSR number.\r
96 db 0Fh, 32h ; rdmsr ; Read EFER.\r
d1471c01 97 db 66h, 0Fh, 0BAh, 0E8h, 08h; bts eax, 8 ; Set LME=1.\r
ea0f431c
JF
98 db 0Fh, 30h ; wrmsr ; Write EFER.\r
99\r
100 db 0Fh, 20h, 0C0h ; mov eax, cr0 ; Read CR0.\r
d1471c01 101 db 66h, 0Fh, 0BAh, 0E8h, 1Fh; bts eax, 31 ; Set PG=1.\r
ea0f431c
JF
102 db 0Fh, 22h, 0C0h ; mov cr0, eax ; Write CR0.\r
103\r
104LONG_JUMP:\r
d1471c01 105 db 66h, 0EAh ; far jump\r
ea0f431c 106 dd 0h ; 32-bit offset\r
d1471c01 107 dw 0h ; 16-bit selector\r
ea0f431c
JF
108\r
109LongModeStart::\r
d1471c01 110 mov eax, edi\r
ea0f431c
JF
111 mov ds, ax\r
112 mov es, ax\r
113 mov ss, ax\r
114\r
115 mov esi, ebx\r
116 mov edi, esi\r
117 add edi, LockLocation\r
118 mov rax, NotVacantFlag\r
119\r
120TestLock:\r
121 xchg qword ptr [edi], rax\r
122 cmp rax, NotVacantFlag\r
123 jz TestLock\r
124\r
125 mov edi, esi\r
126 add edi, NumApsExecutingLoction\r
127 inc dword ptr [edi]\r
128 mov ebx, dword ptr [edi]\r
129\r
130ProgramStack:\r
131 mov edi, esi\r
132 add edi, StackSizeLocation\r
133 mov rax, qword ptr [edi]\r
134 mov edi, esi\r
135 add edi, StackStartAddressLocation\r
136 add rax, qword ptr [edi]\r
137 mov rsp, rax\r
138 mov qword ptr [edi], rax\r
139\r
140Releaselock:\r
141 mov rax, VacantFlag\r
142 mov edi, esi\r
143 add edi, LockLocation\r
144 xchg qword ptr [edi], rax\r
145\r
146CProcedureInvoke:\r
147 push rbp ; push BIST data\r
148 xor rbp, rbp ; clear ebp for call stack trace\r
149 push rbp\r
150 mov rbp, rsp\r
151\r
152 mov rax, InitializeFloatingPointUnits\r
153 sub rsp, 20h\r
154 call rax ; Call assembly function to initialize FPU per UEFI spec\r
155 add rsp, 20h\r
156\r
157 mov edx, ebx ; edx is NumApsExecuting\r
158 mov ecx, esi\r
159 add ecx, LockLocation ; rcx is address of exchange info data buffer\r
160\r
161 mov edi, esi\r
162 add edi, ApProcedureLocation\r
163 mov rax, qword ptr [edi]\r
164\r
165 sub rsp, 20h\r
166 call rax ; invoke C function\r
167 add rsp, 20h\r
168 jmp $\r
169\r
170RendezvousFunnelProc ENDP\r
171RendezvousFunnelProcEnd::\r
172\r
ea0f431c
JF
173;-------------------------------------------------------------------------------------\r
174; AsmGetAddressMap (&AddressMap);\r
175;-------------------------------------------------------------------------------------\r
176AsmGetAddressMap PROC\r
177 mov rax, offset RendezvousFunnelProcStart\r
178 mov qword ptr [rcx], rax\r
01beffa7
JF
179 mov qword ptr [rcx + 8h], LongModeStart - RendezvousFunnelProcStart\r
180 mov qword ptr [rcx + 10h], RendezvousFunnelProcEnd - RendezvousFunnelProcStart\r
ea0f431c
JF
181 ret\r
182AsmGetAddressMap ENDP\r
183\r
184;-------------------------------------------------------------------------------------\r
185;AsmExchangeRole procedure follows. This procedure executed by current BSP, that is\r
186;about to become an AP. It switches it'stack with the current AP.\r
187;AsmExchangeRole (IN CPU_EXCHANGE_INFO *MyInfo, IN CPU_EXCHANGE_INFO *OthersInfo);\r
188;-------------------------------------------------------------------------------------\r
189AsmExchangeRole PROC\r
190 ; DO NOT call other functions in this function, since 2 CPU may use 1 stack\r
191 ; at the same time. If 1 CPU try to call a function, stack will be corrupted.\r
192\r
193 push rax\r
194 push rbx\r
195 push rcx\r
196 push rdx\r
197 push rsi\r
198 push rdi\r
199 push rbp\r
200 push r8\r
201 push r9\r
202 push r10\r
203 push r11\r
204 push r12\r
205 push r13\r
206 push r14\r
207 push r15\r
208\r
209 mov rax, cr0\r
210 push rax\r
211\r
212 mov rax, cr4\r
213 push rax\r
214\r
215 ; rsi contains MyInfo pointer\r
216 mov rsi, rcx\r
217\r
218 ; rdi contains OthersInfo pointer\r
219 mov rdi, rdx\r
220\r
221 ;Store EFLAGS, GDTR and IDTR regiter to stack\r
222 pushfq\r
223 sgdt fword ptr [rsi + 16]\r
224 sidt fword ptr [rsi + 26]\r
225\r
226 ; Store the its StackPointer\r
227 mov qword ptr [rsi + 8], rsp\r
228\r
229 ; update its switch state to STORED\r
230 mov byte ptr [rsi], CPU_SWITCH_STATE_STORED\r
231\r
232WaitForOtherStored:\r
233 ; wait until the other CPU finish storing its state\r
234 cmp byte ptr [rdi], CPU_SWITCH_STATE_STORED\r
235 jz OtherStored\r
236 pause\r
237 jmp WaitForOtherStored\r
238\r
239OtherStored:\r
240 ; Since another CPU already stored its state, load them\r
241 ; load GDTR value\r
242 lgdt fword ptr [rdi + 16]\r
243\r
244 ; load IDTR value\r
245 lidt fword ptr [rdi + 26]\r
246\r
247 ; load its future StackPointer\r
248 mov rsp, qword ptr [rdi + 8]\r
249\r
250 ; update the other CPU's switch state to LOADED\r
251 mov byte ptr [rdi], CPU_SWITCH_STATE_LOADED\r
252\r
253WaitForOtherLoaded:\r
254 ; wait until the other CPU finish loading new state,\r
255 ; otherwise the data in stack may corrupt\r
256 cmp byte ptr [rsi], CPU_SWITCH_STATE_LOADED\r
257 jz OtherLoaded\r
258 pause\r
259 jmp WaitForOtherLoaded\r
260\r
261OtherLoaded:\r
262 ; since the other CPU already get the data it want, leave this procedure\r
263 popfq\r
264\r
265 pop rax\r
266 mov cr4, rax\r
267\r
268 pop rax\r
269 mov cr0, rax\r
270\r
271 pop r15\r
272 pop r14\r
273 pop r13\r
274 pop r12\r
275 pop r11\r
276 pop r10\r
277 pop r9\r
278 pop r8\r
279 pop rbp\r
280 pop rdi\r
281 pop rsi\r
282 pop rdx\r
283 pop rcx\r
284 pop rbx\r
285 pop rax\r
286\r
287 ret\r
288AsmExchangeRole ENDP\r
289\r
ea0f431c 290END\r