]> git.proxmox.com Git - mirror_edk2.git/blame - UefiCpuPkg/Library/MpInitLib/Ia32/MpFuncs.nasm
UefiCpuPkg/MpInitLib: Add EnableExecuteDisable in MP_CPU_EXCHANGE_INFO
[mirror_edk2.git] / UefiCpuPkg / Library / MpInitLib / Ia32 / 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
24SECTION .text\r
25\r
26;-------------------------------------------------------------------------------------\r
27;RendezvousFunnelProc procedure follows. All APs execute their procedure. This\r
28;procedure serializes all the AP processors through an Init sequence. It must be\r
29;noted that APs arrive here very raw...ie: real mode, no stack.\r
30;ALSO THIS PROCEDURE IS EXECUTED BY APs ONLY ON 16 BIT MODE. HENCE THIS PROC\r
31;IS IN MACHINE CODE.\r
32;-------------------------------------------------------------------------------------\r
33global ASM_PFX(RendezvousFunnelProc)\r
34ASM_PFX(RendezvousFunnelProc):\r
35RendezvousFunnelProcStart:\r
36; At this point CS = 0x(vv00) and ip= 0x0.\r
37BITS 16\r
38 mov ebp, eax ; save BIST information\r
39\r
40 mov ax, cs\r
41 mov ds, ax\r
42 mov es, ax\r
43 mov ss, ax\r
44 xor ax, ax\r
45 mov fs, ax\r
46 mov gs, ax\r
47\r
48 mov si, BufferStartLocation\r
49 mov ebx, [si]\r
50\r
51 mov si, ModeOffsetLocation\r
52 mov eax, [si]\r
53 mov si, CodeSegmentLocation\r
54 mov edx, [si]\r
55 mov di, ax\r
56 sub di, 02h\r
57 mov [di], dx\r
58 sub di, 04h\r
59 add eax, ebx\r
60 mov [di],eax\r
61\r
62 mov si, DataSegmentLocation\r
63 mov edx, [si]\r
64\r
65 mov si, GdtrLocation\r
66o32 lgdt [cs:si]\r
67\r
68 mov si, IdtrLocation\r
69o32 lidt [cs:si]\r
70\r
71 xor ax, ax\r
72 mov ds, ax\r
73\r
8396e2dd
JF
74 mov eax, cr0 ; Get control register 0\r
75 or eax, 000000003h ; Set PE bit (bit #0) & MP\r
d94e5f67
JF
76 mov cr0, eax\r
77\r
78 jmp 0:strict dword 0 ; far jump to protected mode\r
79BITS 32\r
80Flat32Start: ; protected mode entry point\r
81 mov ds, dx\r
82 mov es, dx\r
83 mov fs, dx\r
84 mov gs, dx\r
85 mov ss, dx\r
86\r
87 mov esi, ebx\r
5c66d125
JF
88\r
89 mov edi, esi\r
90 add edi, EnableExecuteDisableLocation\r
91 cmp byte [edi], 0\r
92 jz SkipEnableExecuteDisable\r
93\r
94 ;\r
95 ; Enable IA32 PAE execute disable\r
96 ;\r
97\r
98 mov ecx, 0xc0000080\r
99 rdmsr\r
100 bts eax, 11\r
101 wrmsr\r
102\r
103 mov edi, esi\r
104 add edi, Cr3Location\r
105 mov eax, dword [edi]\r
106 mov cr3, eax\r
107\r
108 mov eax, cr4\r
109 bts eax, 5\r
110 mov cr4, eax\r
111\r
112 mov eax, cr0\r
113 bts eax, 31\r
114 mov cr0, eax\r
115\r
116SkipEnableExecuteDisable:\r
117\r
d94e5f67
JF
118 mov edi, esi\r
119 add edi, LockLocation\r
120 mov eax, NotVacantFlag\r
121\r
122TestLock:\r
123 xchg [edi], eax\r
124 cmp eax, NotVacantFlag\r
125 jz TestLock\r
126\r
127 mov edi, esi\r
8396e2dd 128 add edi, NumApsExecutingLocation\r
d94e5f67
JF
129 inc dword [edi]\r
130 mov ebx, [edi]\r
131\r
132ProgramStack:\r
133 mov edi, esi\r
134 add edi, StackSizeLocation\r
135 mov eax, [edi]\r
136 mov edi, esi\r
137 add edi, StackStartAddressLocation\r
138 add eax, [edi]\r
139 mov esp, eax\r
140 mov [edi], eax\r
141\r
142Releaselock:\r
143 mov eax, VacantFlag\r
144 mov edi, esi\r
145 add edi, LockLocation\r
146 xchg [edi], eax\r
147\r
148CProcedureInvoke:\r
149 push ebp ; push BIST data at top of AP stack\r
150 xor ebp, ebp ; clear ebp for call stack trace\r
151 push ebp\r
152 mov ebp, esp\r
153\r
154 mov eax, ASM_PFX(InitializeFloatingPointUnits)\r
155 call eax ; Call assembly function to initialize FPU per UEFI spec\r
156\r
157 push ebx ; Push NumApsExecuting\r
158 mov eax, esi\r
159 add eax, LockLocation\r
160 push eax ; push address of exchange info data buffer\r
161\r
162 mov edi, esi\r
163 add edi, ApProcedureLocation\r
164 mov eax, [edi]\r
165\r
8396e2dd 166 call eax ; Invoke C function\r
d94e5f67 167\r
8396e2dd 168 jmp $ ; Never reach here\r
d94e5f67
JF
169RendezvousFunnelProcEnd:\r
170\r
171;-------------------------------------------------------------------------------------\r
172; AsmGetAddressMap (&AddressMap);\r
173;-------------------------------------------------------------------------------------\r
174global ASM_PFX(AsmGetAddressMap)\r
175ASM_PFX(AsmGetAddressMap):\r
176 pushad\r
177 mov ebp,esp\r
178\r
179 mov ebx, [ebp + 24h]\r
180 mov dword [ebx], RendezvousFunnelProcStart\r
181 mov dword [ebx + 4h], Flat32Start - RendezvousFunnelProcStart\r
182 mov dword [ebx + 8h], RendezvousFunnelProcEnd - RendezvousFunnelProcStart\r
183\r
184 popad\r
185 ret\r
186\r
187;-------------------------------------------------------------------------------------\r
188;AsmExchangeRole procedure follows. This procedure executed by current BSP, that is\r
189;about to become an AP. It switches it'stack with the current AP.\r
190;AsmExchangeRole (IN CPU_EXCHANGE_INFO *MyInfo, IN CPU_EXCHANGE_INFO *OthersInfo);\r
191;-------------------------------------------------------------------------------------\r
192global ASM_PFX(AsmExchangeRole)\r
193ASM_PFX(AsmExchangeRole):\r
194 ; DO NOT call other functions in this function, since 2 CPU may use 1 stack\r
195 ; at the same time. If 1 CPU try to call a function, stack will be corrupted.\r
196 pushad\r
197 mov ebp,esp\r
198\r
199 ; esi contains MyInfo pointer\r
200 mov esi, [ebp + 24h]\r
201\r
202 ; edi contains OthersInfo pointer\r
203 mov edi, [ebp + 28h]\r
204\r
205 ;Store EFLAGS, GDTR and IDTR register to stack\r
206 pushfd\r
207 mov eax, cr4\r
208 push eax ; push cr4 firstly\r
209 mov eax, cr0\r
210 push eax\r
211\r
212 sgdt [esi + 8]\r
213 sidt [esi + 14]\r
214\r
215 ; Store the its StackPointer\r
216 mov [esi + 4],esp\r
217\r
218 ; update its switch state to STORED\r
219 mov byte [esi], CPU_SWITCH_STATE_STORED\r
220\r
221WaitForOtherStored:\r
222 ; wait until the other CPU finish storing its state\r
223 cmp byte [edi], CPU_SWITCH_STATE_STORED\r
224 jz OtherStored\r
225 pause\r
226 jmp WaitForOtherStored\r
227\r
228OtherStored:\r
229 ; Since another CPU already stored its state, load them\r
230 ; load GDTR value\r
231 lgdt [edi + 8]\r
232\r
233 ; load IDTR value\r
234 lidt [edi + 14]\r
235\r
236 ; load its future StackPointer\r
237 mov esp, [edi + 4]\r
238\r
239 ; update the other CPU's switch state to LOADED\r
240 mov byte [edi], CPU_SWITCH_STATE_LOADED\r
241\r
242WaitForOtherLoaded:\r
243 ; wait until the other CPU finish loading new state,\r
244 ; otherwise the data in stack may corrupt\r
245 cmp byte [esi], CPU_SWITCH_STATE_LOADED\r
246 jz OtherLoaded\r
247 pause\r
248 jmp WaitForOtherLoaded\r
249\r
250OtherLoaded:\r
251 ; since the other CPU already get the data it want, leave this procedure\r
252 pop eax\r
253 mov cr0, eax\r
254 pop eax\r
255 mov cr4, eax\r
256 popfd\r
257\r
258 popad\r
259 ret\r