]> git.proxmox.com Git - mirror_edk2.git/blob - UefiCpuPkg/Library/MpInitLib/Ia32/MpFuncs.nasm
UefiCpuPkg/CpuDxe: Enable protection for newly added page table
[mirror_edk2.git] / UefiCpuPkg / Library / MpInitLib / Ia32 / MpFuncs.nasm
1 ;------------------------------------------------------------------------------ ;
2 ; Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>
3 ; This program and the accompanying materials
4 ; are licensed and made available under the terms and conditions of the BSD License
5 ; which accompanies this distribution. The full text of the license may be found at
6 ; http://opensource.org/licenses/bsd-license.php.
7 ;
8 ; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
9 ; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
10 ;
11 ; Module Name:
12 ;
13 ; MpFuncs.nasm
14 ;
15 ; Abstract:
16 ;
17 ; This is the assembly code for MP support
18 ;
19 ;-------------------------------------------------------------------------------
20
21 %include "MpEqu.inc"
22 extern ASM_PFX(InitializeFloatingPointUnits)
23
24 SECTION .text
25
26 ;-------------------------------------------------------------------------------------
27 ;RendezvousFunnelProc procedure follows. All APs execute their procedure. This
28 ;procedure serializes all the AP processors through an Init sequence. It must be
29 ;noted that APs arrive here very raw...ie: real mode, no stack.
30 ;ALSO THIS PROCEDURE IS EXECUTED BY APs ONLY ON 16 BIT MODE. HENCE THIS PROC
31 ;IS IN MACHINE CODE.
32 ;-------------------------------------------------------------------------------------
33 global ASM_PFX(RendezvousFunnelProc)
34 ASM_PFX(RendezvousFunnelProc):
35 RendezvousFunnelProcStart:
36 ; At this point CS = 0x(vv00) and ip= 0x0.
37 BITS 16
38 mov ebp, eax ; save BIST information
39
40 mov ax, cs
41 mov ds, ax
42 mov es, ax
43 mov ss, ax
44 xor ax, ax
45 mov fs, ax
46 mov gs, ax
47
48 mov si, BufferStartLocation
49 mov ebx, [si]
50
51 mov si, ModeOffsetLocation
52 mov eax, [si]
53 mov si, CodeSegmentLocation
54 mov edx, [si]
55 mov di, ax
56 sub di, 02h
57 mov [di], dx
58 sub di, 04h
59 add eax, ebx
60 mov [di],eax
61
62 mov si, DataSegmentLocation
63 mov edx, [si]
64
65 mov si, GdtrLocation
66 o32 lgdt [cs:si]
67
68 mov si, IdtrLocation
69 o32 lidt [cs:si]
70
71 xor ax, ax
72 mov ds, ax
73
74 mov eax, cr0 ; Get control register 0
75 or eax, 000000003h ; Set PE bit (bit #0) & MP
76 mov cr0, eax
77
78 jmp 0:strict dword 0 ; far jump to protected mode
79 BITS 32
80 Flat32Start: ; protected mode entry point
81 mov ds, dx
82 mov es, dx
83 mov fs, dx
84 mov gs, dx
85 mov ss, dx
86
87 mov esi, ebx
88
89 ; Increment the number of APs executing here as early as possible
90 ; This is decremented in C code when AP is finished executing
91 mov edi, esi
92 add edi, NumApsExecutingLocation
93 lock inc dword [edi]
94
95 mov edi, esi
96 add edi, EnableExecuteDisableLocation
97 cmp byte [edi], 0
98 jz SkipEnableExecuteDisable
99
100 ;
101 ; Enable IA32 PAE execute disable
102 ;
103
104 mov ecx, 0xc0000080
105 rdmsr
106 bts eax, 11
107 wrmsr
108
109 mov edi, esi
110 add edi, Cr3Location
111 mov eax, dword [edi]
112 mov cr3, eax
113
114 mov eax, cr4
115 bts eax, 5
116 mov cr4, eax
117
118 mov eax, cr0
119 bts eax, 31
120 mov cr0, eax
121
122 SkipEnableExecuteDisable:
123 mov edi, esi
124 add edi, InitFlagLocation
125 cmp dword [edi], 1 ; 1 == ApInitConfig
126 jnz GetApicId
127
128 ; AP init
129 mov edi, esi
130 add edi, LockLocation
131 mov eax, NotVacantFlag
132
133 TestLock:
134 xchg [edi], eax
135 cmp eax, NotVacantFlag
136 jz TestLock
137
138 mov ecx, esi
139 add ecx, ApIndexLocation
140 inc dword [ecx]
141 mov ebx, [ecx]
142
143 Releaselock:
144 mov eax, VacantFlag
145 xchg [edi], eax
146
147 mov edi, esi
148 add edi, StackSizeLocation
149 mov eax, [edi]
150 mov ecx, ebx
151 inc ecx
152 mul ecx ; EAX = StackSize * (CpuNumber + 1)
153 mov edi, esi
154 add edi, StackStartAddressLocation
155 add eax, [edi]
156 mov esp, eax
157 jmp CProcedureInvoke
158
159 GetApicId:
160 mov eax, 0
161 cpuid
162 cmp eax, 0bh
163 jb NoX2Apic ; CPUID level below CPUID_EXTENDED_TOPOLOGY
164
165 mov eax, 0bh
166 xor ecx, ecx
167 cpuid
168 test ebx, 0ffffh
169 jz NoX2Apic ; CPUID.0BH:EBX[15:0] is zero
170
171 ; Processor is x2APIC capable; 32-bit x2APIC ID is already in EDX
172 jmp GetProcessorNumber
173
174 NoX2Apic:
175 ; Processor is not x2APIC capable, so get 8-bit APIC ID
176 mov eax, 1
177 cpuid
178 shr ebx, 24
179 mov edx, ebx
180
181 GetProcessorNumber:
182 ;
183 ; Get processor number for this AP
184 ; Note that BSP may become an AP due to SwitchBsp()
185 ;
186 xor ebx, ebx
187 lea eax, [esi + CpuInfoLocation]
188 mov edi, [eax]
189
190 GetNextProcNumber:
191 cmp [edi], edx ; APIC ID match?
192 jz ProgramStack
193 add edi, 20
194 inc ebx
195 jmp GetNextProcNumber
196
197 ProgramStack:
198 mov esp, [edi + 12]
199
200 CProcedureInvoke:
201 push ebp ; push BIST data at top of AP stack
202 xor ebp, ebp ; clear ebp for call stack trace
203 push ebp
204 mov ebp, esp
205
206 mov eax, ASM_PFX(InitializeFloatingPointUnits)
207 call eax ; Call assembly function to initialize FPU per UEFI spec
208
209 push ebx ; Push ApIndex
210 mov eax, esi
211 add eax, LockLocation
212 push eax ; push address of exchange info data buffer
213
214 mov edi, esi
215 add edi, ApProcedureLocation
216 mov eax, [edi]
217
218 call eax ; Invoke C function
219
220 jmp $ ; Never reach here
221 RendezvousFunnelProcEnd:
222
223 ;-------------------------------------------------------------------------------------
224 ; AsmRelocateApLoop (MwaitSupport, ApTargetCState, PmCodeSegment, TopOfApStack, CountTofinish);
225 ;-------------------------------------------------------------------------------------
226 global ASM_PFX(AsmRelocateApLoop)
227 ASM_PFX(AsmRelocateApLoop):
228 AsmRelocateApLoopStart:
229 mov eax, esp
230 mov esp, [eax + 16] ; TopOfApStack
231 push dword [eax] ; push return address for stack trace
232 push ebp
233 mov ebp, esp
234 mov ebx, [eax + 8] ; ApTargetCState
235 mov ecx, [eax + 4] ; MwaitSupport
236 mov eax, [eax + 20] ; CountTofinish
237 lock dec dword [eax] ; (*CountTofinish)--
238 cmp cl, 1 ; Check mwait-monitor support
239 jnz HltLoop
240 MwaitLoop:
241 mov eax, esp
242 xor ecx, ecx
243 xor edx, edx
244 monitor
245 mov eax, ebx ; Mwait Cx, Target C-State per eax[7:4]
246 shl eax, 4
247 mwait
248 jmp MwaitLoop
249 HltLoop:
250 cli
251 hlt
252 jmp HltLoop
253 AsmRelocateApLoopEnd:
254
255 ;-------------------------------------------------------------------------------------
256 ; AsmGetAddressMap (&AddressMap);
257 ;-------------------------------------------------------------------------------------
258 global ASM_PFX(AsmGetAddressMap)
259 ASM_PFX(AsmGetAddressMap):
260 pushad
261 mov ebp,esp
262
263 mov ebx, [ebp + 24h]
264 mov dword [ebx], RendezvousFunnelProcStart
265 mov dword [ebx + 4h], Flat32Start - RendezvousFunnelProcStart
266 mov dword [ebx + 8h], RendezvousFunnelProcEnd - RendezvousFunnelProcStart
267 mov dword [ebx + 0Ch], AsmRelocateApLoopStart
268 mov dword [ebx + 10h], AsmRelocateApLoopEnd - AsmRelocateApLoopStart
269
270 popad
271 ret
272
273 ;-------------------------------------------------------------------------------------
274 ;AsmExchangeRole procedure follows. This procedure executed by current BSP, that is
275 ;about to become an AP. It switches it'stack with the current AP.
276 ;AsmExchangeRole (IN CPU_EXCHANGE_INFO *MyInfo, IN CPU_EXCHANGE_INFO *OthersInfo);
277 ;-------------------------------------------------------------------------------------
278 global ASM_PFX(AsmExchangeRole)
279 ASM_PFX(AsmExchangeRole):
280 ; DO NOT call other functions in this function, since 2 CPU may use 1 stack
281 ; at the same time. If 1 CPU try to call a function, stack will be corrupted.
282 pushad
283 mov ebp,esp
284
285 ; esi contains MyInfo pointer
286 mov esi, [ebp + 24h]
287
288 ; edi contains OthersInfo pointer
289 mov edi, [ebp + 28h]
290
291 ;Store EFLAGS, GDTR and IDTR register to stack
292 pushfd
293 mov eax, cr4
294 push eax ; push cr4 firstly
295 mov eax, cr0
296 push eax
297
298 sgdt [esi + 8]
299 sidt [esi + 14]
300
301 ; Store the its StackPointer
302 mov [esi + 4],esp
303
304 ; update its switch state to STORED
305 mov byte [esi], CPU_SWITCH_STATE_STORED
306
307 WaitForOtherStored:
308 ; wait until the other CPU finish storing its state
309 cmp byte [edi], CPU_SWITCH_STATE_STORED
310 jz OtherStored
311 pause
312 jmp WaitForOtherStored
313
314 OtherStored:
315 ; Since another CPU already stored its state, load them
316 ; load GDTR value
317 lgdt [edi + 8]
318
319 ; load IDTR value
320 lidt [edi + 14]
321
322 ; load its future StackPointer
323 mov esp, [edi + 4]
324
325 ; update the other CPU's switch state to LOADED
326 mov byte [edi], CPU_SWITCH_STATE_LOADED
327
328 WaitForOtherLoaded:
329 ; wait until the other CPU finish loading new state,
330 ; otherwise the data in stack may corrupt
331 cmp byte [esi], CPU_SWITCH_STATE_LOADED
332 jz OtherLoaded
333 pause
334 jmp WaitForOtherLoaded
335
336 OtherLoaded:
337 ; since the other CPU already get the data it want, leave this procedure
338 pop eax
339 mov cr0, eax
340 pop eax
341 mov cr4, eax
342 popfd
343
344 popad
345 ret