UefiCpuPkg/MpInitLib: Add EnableExecuteDisable in MP_CPU_EXCHANGE_INFO
[mirror_edk2.git] / UefiCpuPkg / Library / MpInitLib / X64 / MpFuncs.nasm
CommitLineData
d94e5f67
JF
1;------------------------------------------------------------------------------ ;\r
2; Copyright (c) 2015 - 2016, 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
40\r
41BITS 16\r
42 mov ebp, eax ; Save BIST information\r
43\r
44 mov ax, cs\r
45 mov ds, ax\r
46 mov es, ax\r
47 mov ss, ax\r
48 xor ax, ax\r
49 mov fs, ax\r
50 mov gs, ax\r
51\r
52 mov si, BufferStartLocation\r
53 mov ebx, [si]\r
54\r
55 mov di, ModeOffsetLocation\r
56 mov eax, [di]\r
57 mov di, CodeSegmentLocation\r
58 mov edx, [di]\r
59 mov di, ax\r
8396e2dd 60 sub di, 02h\r
d94e5f67
JF
61 mov [di],dx ; Patch long mode CS\r
62 sub di, 04h\r
63 add eax, ebx\r
64 mov [di],eax ; Patch address\r
65\r
66 mov si, GdtrLocation\r
67o32 lgdt [cs:si]\r
68\r
69 mov si, IdtrLocation\r
70o32 lidt [cs:si]\r
71\r
5c66d125
JF
72 mov si, EnableExecuteDisableLocation\r
73 cmp byte [si], 0\r
74 jz SkipEnableExecuteDisableBit\r
75\r
76 ;\r
77 ; Enable execute disable bit\r
78 ;\r
79 mov ecx, 0c0000080h ; EFER MSR number\r
80 rdmsr ; Read EFER\r
81 bts eax, 11 ; Enable Execute Disable Bit\r
82 wrmsr ; Write EFER\r
83\r
84SkipEnableExecuteDisableBit:\r
d94e5f67
JF
85\r
86 mov di, DataSegmentLocation\r
87 mov edi, [di] ; Save long mode DS in edi\r
88\r
89 mov si, Cr3Location ; Save CR3 in ecx\r
90 mov ecx, [si]\r
91\r
92 xor ax, ax\r
93 mov ds, ax ; Clear data segment\r
94\r
95 mov eax, cr0 ; Get control register 0\r
96 or eax, 000000003h ; Set PE bit (bit #0) & MP\r
97 mov cr0, eax\r
98\r
99 mov eax, cr4\r
100 bts eax, 5\r
101 mov cr4, eax\r
102\r
103 mov cr3, ecx ; Load CR3\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 0:strict dword 0 ; far jump to long mode\r
115BITS 64\r
116LongModeStart:\r
117 mov eax, edi\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
8396e2dd 133 add edi, NumApsExecutingLocation\r
d94e5f67
JF
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
8396e2dd
JF
154 push rbp ; Push BIST data at top of AP stack\r
155 xor rbp, rbp ; Clear ebp for call stack trace\r
d94e5f67
JF
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
8396e2dd 173 call rax ; Invoke C function\r
d94e5f67 174 add rsp, 20h\r
8396e2dd 175 jmp $ ; Should never reach here\r
d94e5f67
JF
176\r
177RendezvousFunnelProcEnd:\r
178\r
179;-------------------------------------------------------------------------------------\r
180; AsmGetAddressMap (&AddressMap);\r
181;-------------------------------------------------------------------------------------\r
182global ASM_PFX(AsmGetAddressMap)\r
183ASM_PFX(AsmGetAddressMap):\r
184 mov rax, ASM_PFX(RendezvousFunnelProc)\r
185 mov qword [rcx], rax\r
186 mov qword [rcx + 8h], LongModeStart - RendezvousFunnelProcStart\r
187 mov qword [rcx + 10h], RendezvousFunnelProcEnd - RendezvousFunnelProcStart\r
188 ret\r
189\r
190;-------------------------------------------------------------------------------------\r
191;AsmExchangeRole procedure follows. This procedure executed by current BSP, that is\r
8396e2dd 192;about to become an AP. It switches its stack with the current AP.\r
d94e5f67
JF
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